C語言中static的變量:
1).static局部變量
a、靜態局部變量在函數內定義,生存期爲整個程序運行期間,但作用域與自動變量相同,只能在定義該變量的函數內使用。退出該函數後, 儘管該變量還繼續存在,但不能使用它。
b、對基本類型的靜態局部變量若在說明時未賦以初值,則系統自動賦予0值。而對自動變量不賦初值,則其值是不定的。
2).static全局變量
全局變量本身就是靜態存儲方式, 靜態全局變量當然也是靜態存儲方式。但是他們的作用域,非靜態全局變量的作用域是整個源程序(多個源文件可以共同使用); 而靜態全局變量則限制了其作用域, 即只在定義該變量的源文件(.h或.cpp)內有效, 在同一源程序的其它源文件中不能使用它(注意,這一點和C++是不同的)。
關於C語言static變量的理解:
A、若全局變量僅在單個C文件中訪問,則可以將這個變量修改爲靜態全局變量,以降低模塊間的耦合度;
B、若全局變量僅由單個函數訪問,則可以將這個變量改爲該函數的靜態局部變量,以降低模塊間的耦合度;
C、靜態變量和全局變量放在程序的全局數據區,而不是在堆棧中分配,所以不可能導致堆棧溢出;
D、設計和使用訪問動態全局變量、靜態全局變量、靜態局部變量的函數時,需要考慮重入問題(線程不安全);
C++中靜態數據成員的特點有::
1、靜態數據成員僅僅在初始化時不受訪問權限的約束;
2、靜態數據成員最好不要在.h文件中進行定義(初始化),而是放在.cpp文件中定義(初始化);
3、靜態數據成員被類的所有對象所共享,包括類的派生類的所有對象;——即派生類和基類共享一個靜態成員。
4、靜態數據成員的類型可是所屬類自己,即在一個類中可以聲明該類自己的類型的靜態成員對象,但是,不可以定義普通的成員對象,(指針可以)
5、在const成員函數中,可以修改static成員變量的值。普通成員變量的值,是不能修改的。
6、static成員函數只能訪問static成員,不能訪問非static成員,並且static成員函數不能定義爲virtual、const、volatile 函數。
詳細分析如下:
類體中的數據成員的聲明前加上static關鍵字,該數據成員就成爲了該類的靜態數據成員。
和其他數據成員一樣,靜態數據成員也遵守public/protected/private訪問規則。注意::僅僅是初始化時不遵守public/protected/private的規則。
即:如果是private和protected的靜態成員,只能通過public的靜態成員函數進行調用,而不能通過類名直接訪問了。
1、靜態數據成員的定義(初始化)不能在頭文件中。
靜態數據成員實際上是類域中的全局變量。所以,靜態數據成員的定義(初始化)不應該被放在頭文件中。
其定義方式與全局變量相同。舉例如下:
xxx.h文件
class base
{
private:
static const int _i; //聲明,標準c++支持有序類型在類體中初始化,但vc6不支持。
};
xxx.cpp文件
const int base::_i=10; //僅僅在定義(初始化)時不受private和protected訪問限制.
注:不要試圖在頭文件中定義(初始化)靜態數據成員。在大多數的情況下,這樣做會引起重複定義這樣的錯誤。即使加上#ifndef #define #endif或者#pragma once也不行。
2、靜態數據成員 被 類 的所有對象所共享,包括該類派生類的對象。即派生類對象與基類對象共享基類的靜態數據成員。舉例如下:
class base
{
public :
static int _num; //聲明
};
int base::_num=0; //靜態數據成員的真正定義
class derived:public base
{
};
main()
{
base a;
derived b;
a._num++;
cout<<"base class static data number _num is"<<a._num<<endl;
b._num++;
cout<<"derived class static data number _num is"<<b._num<<endl;
}
// 結果爲1,2;可見派生類與基類共用一個靜態數據成員。
3、靜態數據成員的類型可以是所屬類的類型,而普通數據成員則不可以。普通數據成員的只能聲明爲所屬類類型的 指針或引用。舉例如下:
class base{
public :
static base _object1; //正確,靜態數據成員
base _object2; //錯誤
base *pObject; //正確,指針
base &mObject; //正確,引用 (引用需要在構造函數的參數初始化列表中初始化,如下:)
};
這個類要能創建對象,需要定義帶有參數初始化列表的構造函數,如下:
class base{
public :
static base _object1; //正確,靜態數據成員
base *pObject; //正確,指針
base &mObject; //正確,引用
base():mObject(*this){}
};
4、靜態數據成員的值在const成員函數中可以被合法的改變,而不破那個數據成員的值,不能在const成員函數中改變。
#include <iostream>
using namespace std;
class Student
{
private:
static int a;
int b;
public:
void change() const;
void setB(int b);
int getB();
static int getA();
};
void Student::change() const
{
a++; //這個可以,因爲a是static成員變量。
b++; //不可以,因爲b是普通成員變量(如果b不是成員變量(是全局變量,普通參數,函數內部定義的臨時變量)也可以別修改),且是const函數
}
int Student::getA()
{
return a;
}
void Student::setB(int b)
{
this->b = b;
}
int Student::getB()
{
return b;
}
int Student::a = 5;
int main(int argc,char *argv[])
{
Student stu;
stu.setB(10);
stu.change();
cout<<Student::getA()<<endl;
cout<<stu.getB()<<endl;
return 0;
}
即:成員函數的const約束,只起作用於類的普通成員變量,對於全局變量,成員函數參數,成員函數內部的臨時變量起不到作用。