簡體   English   中英

C ++繼承:在運行時確定繼承的方法

[英]C++ inheritance: determine inherited methods at runtime

我有一個擴展了B的類D,該類又擴展了A。現在,我想添加一個類C,它具有與B完全相同的接口,但是提供了不同的實現。 因此,我將其設計如下: 鑽石

這並不是我想要的,因為我只需要D的一個實例來擴展B或C,而不是兩者都可以,但是,這僅在運行時確定。 上面設計的問題當然是,如果我在D中調用同時在B和C中實現的方法,則該方法是模棱兩可的。

因此,我想在運行時創建B或C的實例,然后將其強制轉換為D。每次D的實例調用繼承的方法時,都應使用其原始對象之一。

我是否需要在每個方法調用周圍擺弄typeid和if / else,還是有一種更優雅的方法呢?

class A{ 
virtual f1();
virtual f2();
}

class B : public virtual A{
f1();
f2();
f3();
}

class C : public virtual A{
f1();
f2();
f3();
}

class D : public B, public C{
f4(){f1(); f3)};
}

...
D* d = new D();
E* e = new E(d);
e->d->f1();
e->d->f4();

然后,將D的實例傳遞給另一個用D填充的類(E),因此,我無法修改D的接口。

我認為您繼承錯誤的方式是,您要做的是在要調用的類D上定義要調用的所有方法,因為類A,類B和C中的虛擬方法都有自己的實現方法。

然后,使用類型為A *的數據結構,用指向類型B和C的對象的指針填充該數據結構,然后調用需要在包含結構A *的指針(即vtable)的數據結構中的所有對象上調用的方法然后,該機制將確保根據實際對象的類型使用類B或C的實現。

請參見具體類和抽象類之間的區別是什么?

聽起來你只是想要

class A{
    virtual void DoMagic() = 0;

};  
class B{
    virtual void DoMagic(){};

};  
class D{
    virtual void DoMagic(){};

};

...
bool INeedB = true;//or false
A* a;
if(INeedB){
    a= new B();
}else{
    a = new C();
}
a->DoMagic(); // will call the appropriate method based on the value of INeedB;

除非D實際上有自己的行為? 然后,您可以查看裝飾器模式 ,並使D成為B或C實例的裝飾器。

編輯:您的D類根本不需要繼承A BC

class D{
    D(A* aObj):a(aObj){}
    void f3(){ a->f1();a->f2();}
    A *a;
};

將上面示例中的A *a替換為D d

C ++是一種靜態類型的語言。 對類型聲明的任何處理都在編譯時進行了詳細說明,因此無法在運行時定義D的繼承圖。

您可能需要的是將A作為B和C(具體實現是虛構的所有相關方法,包括析構函數)作為多態基數,並且D通過包含A * 作為A的“ 所有者 ”在D結構中,將根據輸入將其分配給new Bnew C

D析構函數將調用delete A ,現在您必須確定復制和分配。

我的建議不是使用A *,而是使用std::unique_ptr (將使擁有的對象在Ds之間移動)或std::shared_ptr

如果您需要每個D具有自己的A,則讓A具有clone方法(在B和C中重寫,分別返回new Bnew C ),然后在D的復制ctor和Assign運算符中對其進行調用。

似乎D根本不需要繼承A (或BC )。 相反,它只需要在B的實例或C的實例中調用函數。

您可以這樣實現:

class A
{
public:
    virtual void f1();
    virtual void f2();
};

class B : public A;
class C : public A;

class D
{
   A* b_or_c;

public:
    D(A* a_pointer)
        : b_or_c(a_pointer)
        {}

    void f3()
        {
            b_or_c->f1();
            b_or_c->f2();
        }
};

可以這樣使用:

B b;  // An instance of B
C c;  // An instance of C

D d1(&b);
D d2(&c);

d1.f3();  // Will cause `f1` and `f2` in the object `b` to be called
d2.f3();  // Will cause `f1` and `f2` in the object `c` to be called

暫無
暫無

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

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