2009-03-01 107 views
1

可以在基類中定義一個靜態成員變量,並且有多個派生類,每個派生類都使用它自己的此成員變量的實例?子類的靜態成員變量

下面的代碼編譯成功,並打印正確的輸出,但我仍然不確定做這樣的事情是一種好的做法。 在下面的例子中,如果我明確定義了s的一個實例(通過調用:string A :: s;),但它實際上如何工作,但實際上使用了2個實例?

class A 
{ 
    protected: 
    void SetS(string new_s){s = new_s;} 
    void PrintS(){cout << s << endl;}; 
    private: 
    static string s; 

}; 

class B : public A 
{ 
    public: 
    void foo(){ SetS("bbb"); PrintS();}; 
}; 

class C : public A 
{ 
    public: 
    void foo(){ SetS("ccc"); PrintS();}; 
}; 

string A::s; 

int main() 
{ 
    B b; 
    b.foo(); // results in output: bbb 
    C c; 
    c.foo(); // results in output: ccc 
    b.foo(); // results in output: bbb 
} 

回答

7

的確很遺憾地使用繼承。根據良好的面向對象設計原則,基類應該理想地定義接口並且儘可能地包含儘可能少或者沒有狀態。

這是可行的,因爲您的foo()每次調用時都會重置值A::s。嘗試打印地址A::s。只有一個對象。如果您沒有每次都設置該值,並且您有多個對象使用另一個成員函數bar()來讀取A :: s的值,則這將不起作用。

如果BC對象也在單獨的線程中創建,則可能會遇到同步問題。你會以UB結束。

+0

優秀的答案。 +1。 – 2009-03-01 11:22:41