我不确定要使用的术语,但这是我的例子:
class Base {
public:
virtual void test() = 0;
};
class Mixin {
public:
virtual void test() { }
};
class Example : public Base, public Mixin {
};
int main(int argc, char** argv) {
Example example;
example.test();
return 0;
}
我希望我的Mixin
类实现纯虚函数Base::test
,但是当我编译它时,它说:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:15:13: error: cannot declare variable ‘example’ to be of abstract type ‘Example’
Example example;
^
test.cpp:11:7: note: because the following virtual functions are pure within ‘Example’:
class Example : public Base, public Mixin {
^
test.cpp:3:18: note: virtual void Base::test()
virtual void test() = 0;
^
test.cpp:16:13: error: request for member ‘test’ is ambiguous
example.test();
^
test.cpp:8:18: note: candidates are: virtual void Mixin::test()
virtual void test() { }
^
test.cpp:3:18: note: virtual void Base::test()
virtual void test() = 0;
^
我可以添加using
语句,使其不含糊:
class Example : public Base, public Mixin {
public:
using Mixin::test;
};
但它说我还没有实现它:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:17:13: error: cannot declare variable ‘example’ to be of abstract type ‘Example’
Example example;
^
test.cpp:11:7: note: because the following virtual functions are pure within ‘Example’:
class Example : public Base, public Mixin {
^
test.cpp:3:18: note: virtual void Base::test()
virtual void test() = 0;
^
是否可以这样做?
我知道一个选项是让Mixin
继承自Base
,但在我的情况下,有几个派生类,它们不共享共同的祖先。
答案 0 :(得分:6)
你不能直接让一个类覆盖一个不是它的基类的方法。但是你可以用迂回的方式来做。我将介绍两种方法 - 我更喜欢第二种方法。
Daniel Paul在thinkbottomup.com.au的帖子中对此进行了描述,名为C++ Mixins - Reuse through inheritance is good... when done the right way。
在你的情况下,这就是它的样子:
class Base {
public:
virtual void test() = 0;
};
template <typename T>
class Mixin : public T {
public:
virtual void test() override { /*... do stuff ... */ }
};
class UnmixedExample : public Base {
/* definitions specific to the Example class _not_including_
a definition of the test() method */
};
using Example = class Mixin<UnmixedExample>;
int main(int argc, char** argv) {
Example{}.test();
return 0;
}
CRTP是“奇怪的重复模板模式” - 如果您之前没有看到它,请务必遵循该链接。使用这种方法,我们将使用virtual
继承说明符来避免歧义,与前一种方法不同 - 我们不会颠倒Mixin
和Example
类的继承顺序。
class Base {
public:
virtual void test() = 0;
};
template <typename T>
class Mixin : virtual T {
public:
virtual void test() override { /*... do stuff ... */ }
};
class Example : public virtual Base, public virtual Mixin<Base> {
/* definitions specific to the Example class _not_including_
a definition of the test() method */
};
int main(int argc, char** argv) {
Example{}.test();
return 0;
}
注意两种解决方案:
答案 1 :(得分:4)
你不能让一个类覆盖一个不相关的类的虚函数。你可以做些不同的事情来解决这个问题。您可以将mixin设置为(几乎)从类型参数派生的模板,并将其用作class Example : public virtual Base, Mixin
,或者您可以在最终类中添加代码以分派到混合:
void Derived::test() { Mixin::test(); }