使用抽象基类的C ++虚拟继承

时间:2014-06-25 12:22:26

标签: c++ inheritance virtual abstract base

我试图明确表达我的意图,因为可能有不止一种方法。首先,我有一个带有虚函数FooBase的抽象基类SayHi()Foo1是众多派生类之一。

class FooBase {
public:
    virtual void SayHi() = 0;
};

class Foo1 : public FooBase {
public:
    virtual void SayHi() {
        std::cout<<"Foo1 says Hi\n";
    }
};

我还有一个Component课程,有时我想将Foo..课程设为Components。我使用了模板类,因此FooBase的任何子类都可以有Component包装。

class FooComponentBase : public Component {
public:
    virtual FooBase& GetFoo() = 0;
};

template <class T>
class FooComponent : public FooComponentBase {
private:
    T m_foo;
public:
    virtual FooBase& GetFoo() {return m_foo;}
};

现在FooComponentBase是包含FooBase的任何子类的组件的接口:

void DoTest() {
    FooComponentBase* pFooComponent = new FooComponent<Foo1>;
    pFooComponent->GetFoo().SayHi();                            // "Foo1 says Hi"
    delete pFooComponent;
}

到目前为止,这很好,这很有效。但如果FooComponent继承自FooBase,则可能更为简洁,因此我们无需通过GetFoo()访问FooBase方法。

// Inherited version

class FooComponentBase : public Component {};

template <class T>
class FooComponent : public FooComponentBase, public T {};

不幸的是,FooComponentBase无法访问FooBase,即使其所有派生类都有;

void DoTest() {
    FooComponentBase* pFooComponent = new FooComponent<Foo1>;
    pFooComponent->SayHi();     // Error, FooComponentBase has no SayHi() function
    delete pFooComponent;
}

我无法找到一种方法来完成这项工作。似乎应该有一种方法,可能使用虚拟继承;

class FooComponentBase : public Component, virtual public FooBase {};

但是那也不会编译,因为我们无法实例化一个抽象类。我希望我的意图很清楚,我想让FooComponentBase成为一个抽象的基类,比如FooBase但是Component继承,所以我可以使用它来访问每种风格的FooComponent。 有没有一个巧妙的方法来做到这一点?

1 个答案:

答案 0 :(得分:2)

如果您在一个地方使用虚拟继承,如果您想要使用相同的基础实现,则必须在任何地方使用虚拟继承:

class Foo1 : public virtual FooBase {

另一种不太好但可能适合你的方法是在FooBase中实现FooComponent的所有功能:

class FooComponentBase : public Component, public FooBase {
};

template <class T>
class FooComponent : public FooComponentBase {
private:
    T m_foo;
public:
    void SayHi() {m_foo.SayHi();}
};

甚至:

class FooComponentBase : public Component, public FooBase {
};

template <class T>
class FooComponent : public FooComponentBase, public T {
public:
    void SayHi() {T::SayHi();}
};