2013-07-15 139 views
3

我已經搜索了一些SO文章,但還沒有發現任何東西(但),相當我的問題。道歉,如果這個答案已經存在的地方。C++嵌套類

背景第一的位......

我要代表一個設備與功能「部分」,其中的功能具有分層樹形結構。而不是有扁平功能的負載像

DeviceReferenceCheck(), 
DeviceRefereceSet(), 
DevicePhaseSetX(), 
DevicePhaseDefaultsSet...() 

我反而想利用嵌套類,所以我可以得到

dev.reference.check() 
dev.reference.set() 
dev.phase.setx() 
dev.phase.defaults.set...() 

要做到這一點,我嘗試使用嵌套類,將得到obj.func.subfunction.subsub....()結構。嵌套類需要對最外層類的引用,因爲它們需要使用那裏提供的讀/寫函數。

在我的嘗試中,我不明白的第一件事情如下...我自己嘗試過,但因編譯器警告而停止使用它。

class GPIBDevice_Agilent53132A : public GPIBDevice 
{ 
private: 
    class RefOsc { 
    public: 
     // ... snip ... 
     RefOsc(GPIBDevice_Agilent53132A &parent); 
     // ... snip ... 
    } ro; 
public: 
    // ... snip ... 
    GPIBDevice_Agilent53132A(); 
    // ... snip ... 
}; 

GPIBDevice_Agilent53132A::GPIBDevice_Agilent53132A() : GPIBDevice(), ro(*this) 
{ 
} 

編譯器說:gpibdevice_agilent53132a.cpp(5): warning C4355: 'this' : used in base member initializer list

啊哈,我認爲自己...聰明的編譯器...在初始化列表中使用this可能不是一個好主意,因爲類尚未完全構造。

問題1: 我上面說的正確嗎?在封閉類的初始化列表中使用this爲嵌套類提供對封閉類的引用,這是一個壞主意?我的想法是「是」,但希望澄清一下,因爲在其他SO線程中,我已經看到使用這種方法(Nested Class member function can't access function of enclosing class. Why?)。

我的方法來解決這個問題是有一個成員指針嵌套,然後實際上在構造函數中(所以現在可以安全地使用這個類作爲構造)作出了一個新的內部類,我可以傳入參考*沒有警告。這是做這件事的標準方式嗎?

繼續上....

的原因私有嵌套類是順便說一句,我不希望用戶能夠實例化類的他/她。現在,我確實已經公開了...嘗試在嵌套類中使用私有構造函數,但編譯器告訴我它不能構造類。所以大概封閉類可以看到嵌套的類私有數據成員?

問題2: 爲什麼不能封閉類看到嵌套類的私有數據成員/功能?

我的工作是爲了讓嵌套類聲明封閉類作爲朋友。這真的有必要嗎?

謝謝你幫助傢伙!

+2

在初始值設定項列表中使用'this'不是一個好主意,因爲如果您訪問尚未構造的類的成員,您的程序可能會崩潰。話雖如此,如果您只是存儲指針以備將來使用,則不會有任何問題。 – mkirci

+0

如果基類ctor只存儲引用,則它是安全的。在這種情況下,我不會馬上把它稱爲一個壞主意,但我會仔細看看這個設計,因爲它可能是其他問題出現的標誌。 –

+0

好的,謝謝你們。我解決這個問題的方法是讓一個成員指針嵌套,然後當實際在構造函數中(因此現在可以安全地使用這個類作爲構造函數)創建了一個'new'內部類,我可以將引用傳遞給' *這個'沒有警告。這是做這件事的標準方式嗎?我提到的另一個SO線程是如何使用前一種方法的? – Jimbo

回答

2

摘要

感謝Jan他的curiously recurring template pattern的解釋。這是一個有趣的方法要知道。

我已經接受了我自己的答案,因爲我覺得它直接回答了問題。 CRTP方法雖然不錯,但並不直接回答問題,但確實提供了一個很好的選擇。

問題1:

這似乎認爲這是可能的。感謝mkirciR. Martinho Fernandes,以確認我對編譯器生成警告的原因以及忽略它是否「安全」的懷疑。

總之...在構造函數的初始化列表中使用this不是最好的想法,因爲該類尚未構造。正如這些人指出的那樣,如果使用指針,這可能會導致UB。我決定使用我的工作,使用指向內部類的指針,然後在外部類構造函數中創建它......這樣,外部類已經創建並可以將引用傳遞給內部安全地上課。

問題2:

從C++標準,我已發現在部分11.7(很多的挖掘後):

嵌套類是一個部件,因此具有與任何其他成員相同的訪問權限。封閉類的成員對嵌套類的成員沒有特殊的訪問權限;應遵守通常的訪問規則(第11章)。

該標準給出了以下例子:

class E { 
    int x; 
    class B { }; 
    class I { 
     B b; // OK: E::I can access E::B 
     int y; 
     void f(E* p, int i) { 
      p->x = i; // OK: E::I can access E::x 
     } 
    }; 

    int g(I* p) { 
     return p->y; // error: I::y is private 
    } 
}; 

所以,這是(煩人)爲什麼我的外部類不能調用內部類的私有構造函數。我的解決方法是讓外部班級成爲內部班級的朋友。在上面的例子中,我將friend E;添加到內部類decl中。