[英]C++ change member type in derived class
我有一個 class Base1,其中包含不同 class Base2 的對象數組。 我想要一個派生的 class Derived1,它繼承 Base1 的所有內容,除了數組是 Derived2 類型(它是 Base2 的派生 class)。 例如,像這樣:
class Base2{
int a2;
};
class Derived2: public Base2{
int b2;
};
class Base1{
Base2* list;
};
class Derived1: public Base1{
Derived2* list;
};
我的理解是,在上面的例子中,Derived1 的 object 實際上有兩個 arrays:
list
和
Base1::list
我不想要。
這個想法是 Base1 的所有功能仍應適用於 Derived1 object,因為 Derived2“是”Base2。 這真的很臟,但我想我可以在 Derived1 構造函數中刪除 [] Base1::list 數組。
有沒有人看到這個解決方案? 這似乎是經常發生的事情,我無法相信一個簡單的解決方案不存在。 使用模板會起作用嗎? 我的想法是否定的,因為 Base1 和 Derived1 中的所有功能都需要知道它們分別處理 Base2 和 Derived2 對象。
當有人將Derived1
class 向下轉換為Base1
時,您期望會發生什么? 在破壞基礎 class 后使用list
時,它將崩潰。 最好的辦法是繼續使用基類的list
,並確保僅將Derived2
類型的對象放入列表中。 如果列表的內容不能從外部修改,那將是可行的並且是安全的。
是的,我知道對此還有很多話要說,但讓我們一步一步來。
在一般情況下,您嘗試做的事情似乎很危險,但我假設您知道風險;)
我可以提出兩種解決方案:
選項1:
您可以將實際指針隱藏在protected
的部分並提供訪問 function。
class Base1 {
protected:
void *ptr
public:
Base2 *list() {return (Base2*)ptr;}
};
class Derived1 : public Base1 {
public:
Derived2 *list() {return (Derived2*)ptr;}
};
基本上, Base2::list
將被Derived2::list
隱藏。 請注意,您不能將它們設為虛擬並從虛擬中受益。 返回類型必須在編譯時知道。
選項 2:
您可以使用模板化基礎 class。
template <typename T>
class List {
public:
T *list
//implement all functionality which is common, regardless of the type T
};
class Base1 : public List<Base2> {
//specifics for Base2 type
};
class Derived1 : public List<Derived2> {
//specifics for Derived2
};
請注意,在此構造中,Base1 和 Derived1 沒有直接關系,而是有一個共同的祖先。
我將從 Base1 中刪除 Base2 的數組,並使用列表創建一個新的 class:
class Base2{
int a2;
};
class Derived2: public Base2{
int b2;
};
class Base1{
};
class Base1WithList : public Base1{
Base2* list;
};
class Derived1: public Base1{
Derived2* list;
};
我認為沒有任何簡單的方法可以解決您的問題。
我會使用以下方法之一 -
選項 1通過將 Base2* 列表設為私有來隱藏(在 base1 類中),並將其保存為由派生的 class(派生 1)繼承。 當然,在 base1 class 中定義一個 getter function 以訪問該列表。
選項 2只需將 base1 class 中的列表類型更改為(指向)Derived2 的指針,並依賴於指向派生 class 的指針與指向其基 ZA2F2ED4F8EBC2CBB4C21A29DC4 的指針類型兼容的事實。
選項 3忘記 inheritance 並使用模板。 您只需在實例化 object 時指定類型(Base2* 或 Derived2*),生活將再次美好。
@ildjarn 的問題評論給了我類似問題的解決方案:
class Base {
Base* children;
};
class Derived : public Base {
int answer;
public:
void give_answer() {
this->answer == 42;
for(auto child : this->children) {
// at this point `give_answer` is not defined for items of `children`
child->give_answer(); // -> error: ‘class Base’ has no member named ‘give_answer’
}
};
};
解決方案是將虛擬 function 引入Base
:
class Base {
Base* children;
public:
virtual void give_answer();
}
virtual void give_answer() = 0;
也可以,使Base
抽象。
(這個例子有點做作,因為為什么甚至有Base
,但在我的用例中Derived
實際上是Derived<T>
,並且Base
是一個完整的樹實現。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.