C語言中的static變量和C++靜態數據成員 的訪問情況

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約束,只起作用於類的普通成員變量,對於全局變量,成員函數參數,成員函數內部的臨時變量起不到作用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章