2011-05-11 64 views
6

兩個班走的構造我有繼承三類如下:是否可以調用一個超類,在C++當前類

Class_A 
Class_B : public Class_A 
Class_C : public Class_B 

Class_A包含一個構造函數:

public: Class_A(const char *name, int kind); 

Class_B不包含該構造函數。

Class_C我希望調用Class_A的構造函數。喜歡的東西:
Class_C(const char *name, int kind) : Class_A::Class_A(name,kind) {}

的問題是,我不能中間構造添加到Class_B,因爲Class_B時產生的再生每次我做清潔時碼。所以我不能對Class_B做任何持久的修改。不用說,構造函數的Class_C上述行給出了error: "type 'Class_A' is not a direct base of ' Class_C '".

有沒有辦法,我可以調用的Class_A構造在子類中Class_C的方式,而不需要在Class_B同類型構造的?

+0

難道你不能改變生成B的代碼嗎? – Xeo 2011-05-11 09:09:21

+0

在所有'Class_'前綴中都有。 – 2011-05-11 09:31:28

回答

4

如果您無法更改生成B的代碼,那麼您的運氣不好,AFAIK。但是如果A類包含這樣的構造函數,也許你可以通過添加一個簡單的成員函數來設置這兩個變量,並從C構造函數中調用它?可能不如效率高,但至少可以工作。

+0

好主意!我已經按照你的建議實現了Class_C的構造函數,並且它完美地工作。我在複製構造函數中也遇到了一些需要構造函數的問題,但我想我已經用你的建議來解決這個問題。我只希望沒有其他的超類,我忽略了它的初始化。 – 2011-05-11 11:45:40

0

如果生成B,則更改生成器,否則註定要失敗。

根據B在做什麼,可能是一個解決方案,將您的設計更改爲直接從A和B派生C(如果A是您的容器類,B是處理類)。這樣做可能需要模板B.如果B需要對A成員執行操作,則仍然可以給A指針指向B構造函數...

0

您可以爲Class_B添加一個構造函數,它具有與ctor Class_A,然後讓Class_C在ctor中調用。

此外,ctor類初始化列表無法爲基類中的成員設置值(不管它們是privateprotected還是public)。你必須使用基類'ctor來設置它們。

+0

呃。 OP表示他/他不能向B添加Ctor,因爲B是生成的...... – Xeo 2011-05-11 09:26:34

0

通過語言,不能訪問非直接基礎構造函數。

順便說一句,如果Class_A構造函數簽名,

Class_A(const char *name, int kind); 

然後,Class_B應該有一些構造將招待了Class_A構造給定類型的。否則,它會給編譯器錯誤。

擺脫該錯誤的唯一方法是提供Class_A::Class_A(...)的默認參數。

+0

'Class_A'可能包含Class_B調用的類... – Xeo 2011-05-11 09:28:09

+0

@Xeo,有問題OP提到:'Class_B'確實不包含該構造函數。 – iammilind 2011-05-11 09:40:26

1

如果你能夠讓基類的虛基類,你可以做到這一點,因爲虛基類必須在最直接構造總是初始化。如果你不能改變ClassB的從A繼承怎麼你總是可以做到這一點:

RealClassA 
ClassA : public virtual RealClassA 
ClassB : public ClassA 
ClassC : public ClassB 

然後在ClassC構造函數可以直接調用RealClassA(...)

通常這個功能虛擬繼承是一個真正的痛苦,但它可能實際上幫助你在這裏。

1

你可能釀(假設你不能改變B類的代),但如果恰巧是對於B是模板任何構造函數,那麼你就可以專注一個(一個獨特的虛擬類)和創建自己的自定義構造函數與任何基類-A結構你覺得....

否則,雖然效率較低,明顯,安全,乾淨的方法是使用A的operator=(如果有的話)來獲得值你想要進入它...

C c; 
c = A(x, y); 

如果這些字段只能設置在施工的時候,這是一個更難的問題... ...

(步進瞬間深入未定義行爲的可怕的土地,你可以調用A的析構函數,然後放置它new它,但A的壽命是爲了跨越Bs和Cs 。實際上,明顯的風險是,創建類似的東西,B或C已經持有一個指針,並可能嘗試析構函數釋放之後使用堆分配的值....)

1

唯一的可能性是Class_B實際上從 Class_A;在這種情況下,Class_A的構造函數將從派生類最多的位置調用 。但是,因爲這也將涉及改變 代碼生成,或輸入到代碼生成器,你還不如 以及改變它的附加構造函數添加到Class_B

如果你真的不能更改代碼生成器或者其的方式, 會導致它產生額外的構造函數的輸入,但你可以改變 和Class_AClass_C,那麼有兩種可能的解決方案:

  • 最簡單的就是使用延遲初始化;函數添加到 Class_A構造完成後,其採取相應的參數,並執行 初始化。儘管最簡單的 只能使用Class_A以支持默認 構造,並且如果Class_A的所有成員都支持 賦值,但其語義使得默認構造遵循 通過賦值具有相同的結果如使用 你提供的參數(即沒有參考成員,沒有noncopiable成員,沒有 const成員等)建設。
  • 或者,你可以把所有的功能(或者至少 數據成員)的Class_A在一個單獨的類,並有Class_A 從這個類派生幾乎。然後Class_C將調用這個新類的構造函數 。
  • 相關問題