2011-06-14 80 views
0

在類中使用靜態類成員是常見操作。考慮以下定義:使用正在定義的類的靜態類成員

foo.h中

class foo 
    { 
    public: 
     virtual ~foo(); 
    protected: 
     foo(); 
     static foo ms_oFooStaticObject; 
    } 

Foo.cpp中

foo foo::ms_oFooStaticObject; 
    foo::foo(){} 
    foo::~foo(){} 
    void main() 
    { 
     int i; 
    } 

在編譯上面的代碼沒有編譯器錯誤,你可以簡單的步驟模式下運行,並觀察靜態C-tor正在執行。

這怎麼可能?這是一個編譯器錯誤?

我使用Visual Studio 2005(專業版)與SP1(SP.050727-7600)

+3

當面對一個「奇怪」的行爲時,假設編譯器有一個bug是你應該做的最後一件事**。您對您提供的代碼有何期望? – ereOn 2011-06-14 09:23:13

+0

附註:不要使用'void main'。 – 2011-06-14 09:45:24

回答

1

@ user797308:我想你也沒問題,如果有人聲明和定義一個名爲ms_oFooStaticObject全局變量。換句話說,而不是定義foo foo::ms_oFooStaticObject;定義foo ms_oFooStaticObject;(這將需要構造函數是公開的,當然)。

普通老香草全局變量通過extern <type> <global_name>;聲明並使用<type> <global_name>;(可能有一些初始值)定義。

類中的那些靜態成員實際上只是全局變量,類名前加上了它們的名稱。類定義正在聲明它們。想想類foo中ms_oFooStaticObject的聲明與extern foo ms_oFooStaticObject;類似。如何定義變量?這就是foo foo::ms_oFooStaticObject;聲明正在做的事情。

與globals的比較很適合。有很多與全局相關的行李。將類的靜態成員想象爲具有與全局變量相同類型的問題是一個好主意。

編輯

謝里夫的迴應引發了思考。 user797308的問題可能是foo::ms_oFooStaticObject本身受到保護,那麼它如何在文件範圍內定義呢?答案是,因爲語言要求在文件範圍內定義這些靜態數據成員,所以語言當然必須允許這樣的定義,即使對於具有非公開可見性的靜態成員也是如此。

+0

非常感謝。這對我來說確實是一個亮點,它解釋了使用情況。 – NirMH 2011-06-14 11:28:37

4

這不是一個編譯器錯誤 - 建設類的靜態情況下被定義不會觸發遞歸建設(作爲非foo類型的靜態成員會這樣做),所以它非常好。

ms_oFooStaticObject的定義(在Foo.cpp中)的點,foo是一個完整的類型,它的構造,雖然protected,是ms_oFooStaticObject訪問。

foo foo::ms_oFooStaticObject; 

要調用的class foo對象:

0

構造foo::foo()是因爲你在Foo.cpp中的文件做了static變量定義執行。

0

讓我猜。我想你想知道因爲fooprotected,所以你認爲下面這行必須給出錯誤,因爲它試圖從外部調用非公共構造函數。

foo foo::ms_oFooStaticObject; //definition lies outside the class 

好吧,那是不正確的。 ms_oFooStaticObject不是一個全球性的對象,儘管起初似乎是它是,看到它在班級之外的定義。

事實是,ms_oFooStaticObject仍然類的成員,即使其定義是在類之外。而像任何成員,它可以訪問不僅protected的成員,它可以訪問甚至private的:

class A 
{ 
    A() { cout << "constructed" << endl; } //private constructor 
    static A a;        
}; 

A A::a; //okay - member has access to private constructor! 
A b;  //error - non-member doesn't has access to private constructtor 

編譯並看到錯誤消息,行號:http://www.ideone.com/qocH0

順便說一句,你的main()是非標準的,它應該是其中之一:

int main(); 
int main(int argc, char *argv[]);