簡體   English   中英

多個 inheritance:第一鹼基 class 依賴於 function 在第二鹼基 ZA2F2ED4F8EBC4061D

[英]Muiltple inheritance: first base class dependent on function in the second base class

我有很多不同的子類(15+),它們都在其中定義了相同的 function centerAt 這些子類每個都繼承了 extern 庫中的不同類:它們的共同點是它們具有setPos所依賴的 function setPos。

我的目標是避免代碼重復,因此我想出了一個解決方案,將 centerAt 移動到一個基礎 class ,所有子 class 都可以與來自外部庫的基類一起繼承:多個 Z5FED3411FAF832174EF1F040028B2C21

我想出了這段代碼

class InternalBase {
public:
    void centerAt(int x, int y) {
        // Do some math
        setPos(newx, newy)
    }
    virtual void setPos() = 0; // Should be replaced by the setPos in ExternalBase
};

// There are 15+ different external base classes used, here only 2 are shown
class ExternalBase1 { // this is from an external library
public:
    void setPos() { /* internal definition */} 
};

class ExternalBase2 { // this is from an external library
public:
    void setPos() { /* internal definition */} 
};
class Child1 : public InternalBase, public ExternalBase1 {
public:
    // A lot of different functions
};

class Child2 : public InternalBase, public ExternalBase2 {
public:
    // A lot of different functions
};

int main() {
    Child1 myobj;
    myobj.centerAt(120, 394);
    return 0;
}

不幸的是,無法構造 object:編譯器抱怨這是一個抽象的 class - 可能是因為setPos不是從ExternalBase1繼承的。 我該如何解決這個問題,所以Child1ExternalBase1InternalBase繼承setPos從而可以使用ExternalBase1中定義的setPos

此問題與使用並行基礎 class 方法覆蓋純虛擬方法相同? ,但最大的問題是,因為我正在處理一個外部庫,所以無法使用給定的解決方案(使ExternalBase1先繼承InternalBaseclass ExternalBase1: public virtual InternalBase )。

我想避免使用模板。

使用模板是最簡單的解決方案。 模板是 C++ 的獨特功能之一,沒有理由不使用它們。

template<typename T>
class ExternalBaseMixin : public InternalBase, public T {

public:
    using T::T;

    void setPos(int x, int y) override
    {
        T::setPos(x, y);
    }
};

而已。 然后,這只是一個問題:

class Child1 : public ExternalBaseMixin<ExternalBase1> {

// ...

class Child2 : public ExternalBaseMixin<ExternalBase2> {

// ...

ETC...

沒有可比的內置、非模板 C++ 功能可以完成同樣的事情。 任何非模板解決方案最終都會做與此完全相同的事情,但輸入更多,代碼更多,結果更容易出錯。 這是相當安全的,只要滿足一個要求:總是從ExternalBaseMixin繼承。 只要發生這種情況,一切都會以正確的順序被覆蓋並組合在一起。 另外,這也保證了 inheritance 的順序: InternalBase在外部 class 之前構建,如果這很重要的話。

您可以使用 CRTP 並使InternalBase成為模板類型。

這會對您的代碼進行很少的更改。

template <class Derived>
class InternalBase {
public:
    void centerAt(int x, int y) {
        // Do some math
        Derived& derived = static_cast<Derived&>(*this);
        derived.setPos(x, y);
    }
};

class ExternalBase1 { 
public:
    void setPos(int x, int y) {} 
};

class Child1 : public InternalBase<Child1>, public ExternalBase1 {
};

int main() {
    Child1 myobj;
    myobj.centerAt(120, 394);
    return 0;
}

在這里查看它的工作原理: https://godbolt.org/z/Tsej4Gcfd

快速解決您的問題的方法是在每個孩子上明確定義要使用的 setPos() function。 (我調整了一些定義不明確的代碼,我猜這是一個例子,但是 setPos 和提供的虛擬定義在簽名中不匹配):

#include <iostream>

class InternalBase {
public:
    void centerAt(int x, int y) {
        // Do some math
        setPos(x, y);
    }
    virtual void setPos(int x, int y) = 0;
};

class ExternalBase1 {
public:
    void setPos(int x, int y) { std::cout << "Inside ExternalBase1::setPos" << std::endl; } 
};

class Child1 : public InternalBase, public ExternalBase1 {
public:
    void setPos(int x, int y) { ExternalBase1::setPos(x, y); } 
    // A lot of different functions
};

int main() {
    Child1 myobj;
    myobj.centerAt(120, 394);
    return 0;
}

盡管我建議,如果您有時間,嘗試從不同的方法解決構建代碼的問題(模板在這里是理想的,正如已經有人回答的那樣)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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