[英]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
B
或C
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 B
或new C
D析構函數將調用delete A
,現在您必須確定復制和分配。
我的建議不是使用A *,而是使用std::unique_ptr
(將使擁有的對象在Ds之間移動)或std::shared_ptr
。
如果您需要每個D具有自己的A,則讓A具有clone
方法(在B和C中重寫,分別返回new B
和new C
),然后在D的復制ctor和Assign運算符中對其進行調用。
似乎D
根本不需要繼承A
(或B
或C
)。 相反,它只需要在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.