0

我有一个扩展 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 的接口。

4

4 回答 4

2

我认为你的继承方式是错误的,你所做的就是将你想要调用的所有方法定义为你称之为 D 类的虚拟方法在 A 类中,B 类和 C 类都有自己的这些方法的实现.

然后使用 A* 类型的数据结构,用指向 B 和 C 类型对象的指针填充它,然后调用需要调用的方法,该方法需要调用包含 A* 类型指针的数据结构中的所有对象,即 vtable然后机制将确保根据实际对象的类型使用 B 类或 C 类的实现。

请参阅具体类和抽象类有什么区别?

于 2013-01-24T07:18:32.780 回答
1

听起来你只是想要

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

于 2013-01-24T07:16:31.613 回答
0

C++ 是一种静态类型语言。无论您对类型声明做什么,都会在编译时详细说明,因此D无法在运行时定义继承图。

您可能需要的是A作为 B 和 C(具体实现)的多态基础(所有相关的虚拟方法,包括析构函数),并且 D 是“所有者A”,通过包含 A* 将在 D 构造时分配给 anew Bnew C取决于输入。

D 析构函数将调用delete A,现在您必须决定复制和分配。

我的建议是不要使用 A*,而是使用std::unique_ptr(将使拥有的对象在 Ds 之间移动)或std::shared_ptr.

如果您需要每个 D 有自己的 A,那么让 A 有一个clone方法(在 B 和 C 中重写,分别返回 anew Bnew C)并在 D 的复制 ctor 和分配运算符中调用它。

于 2013-01-24T08:46:41.580 回答
-1

似乎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
于 2013-01-24T07:17:05.827 回答