簡體   English   中英

C++ 更改派生 class 中的成員類型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM