我会尽力阐明我的意图,因为可能有不止一种方法可以实现这一点。首先,我有一个带有虚函数 SayHi()
的抽象基类 FooBase
。 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
任何子类的组件的接口(interface):
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
的每种风格。
有没有一种巧妙的方法来做到这一点?
最佳答案
如果您在一处使用虚拟继承,并且希望使用相同的基本实现,则必须在所有地方使用它:
class Foo1 : public virtual FooBase {
另一种方法,虽然不太好,但可能适合您,是在 FooComponent
中实现 FooBase
的所有函数:
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();}
};
关于具有抽象基类的 C++ 虚拟继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24408567/