2010-04-12 91 views
3

上下文1:D類:public B1,public B2 {};在初始化列表中使用超類的地址/指針

背景2:B2採用B1初始化:B2(B1 *)// B2的構造

我的問題是,在D的初始化列表:

d :: d():B1(),B2 (?)... 應該在什麼地方?

我不想把 「(B1 *)本」 的?因爲在初始化列表中使用「this」並不好。由於B1部分已經初始化,所以使用它是有意義的。

我該怎麼辦?

回答

3

這是確定使用的thisB1一部分,因爲它已經被初始化。 §12.6.2/ 5:「直接基類應按聲明順序進行初始化,因爲它們出現在基本說明符列表中(不管mem初始化程序的順序如何)。」

這裏的基地說明符列表是class D : public B1, public B2,而mem-initializer-list是D::D() : B1(), B2(…)

雖然我會說這有「代碼味道」。

編輯:現在我明白您的顧慮,this是否在構造函數,它不包括成員初始化的體外不確定的。允許這種語言被埋在兩個例子之間,我首先錯過了它。第7段:「mem-initializer的表達式列表中的名稱將在指定了 mem初始化程序的構造函數的作用域中進行評估。」

如果B2實際上需要保留一個指向B1的指針,並且該指針始終指向派生最多的對象,請考慮虛擬繼承。

class B1 {}; 
class B2 : virtual B1 {}; // under the hood, B2 has a pointer to B1. 
class D : public virtual B1, public B2 {}; // D has a pointer too 
// Only the most-derived class (the one actually used for instantiation) 
// implements space for and initialization of the B1. 
+0

對我來說,B1和B2不是繼承關係,我不想爲了解決這個問題而改變B2。 – 2010-04-12 07:17:40

1

這是有風險的代碼。正如前面指出的那樣,B1是在B2之前構建的,所以你可以安全地做到這一點,但是如果類定義的改變不再是這種情況,並且它在代碼中不相關的地方,所以你看不到當你打破它時你破壞了代碼。

我會仔細看看這個設計 - 是否有可能改變它使之變得不必要?你能將事物移入成員來封裝而不是繼承 - D真的是B1和B2嗎?

+0

常見的情況是,一個成員依賴另一個成員,如果定義發生變化,開發人員有責任改變實現。 我可以改變我的設計,這很容易,但我想發現這個問題的技術方面,因爲它是有道理的。 – 2010-04-12 07:22:55

+0

@JQ:你說「會員」而不是「基地」。如果他們真的是會員,那麼你就沒有這個問題。他們? – Potatoswatter 2010-04-12 07:30:27

+0

@Patatoswatter:我再次重複以下內容 「我可以改變我的設計,這很容易,但我想發現這個問題的技術方面,因爲它是有意義的」 – 2010-04-13 02:25:49