如何重写另一个基类中的函数
How to override a function in another base class?
我不确定要使用的术语,但这是我的例子:
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
继承,但就我而言,有几个派生类,它们没有共同的祖先。
不能直接让类重写不属于其基类的方法。但是你可以用迂回的方式做到这一点。我将介绍两种这样的方法 - 我更喜欢第二种。
方法1
丹尼尔·保罗(Daniel Paul)在一篇关于 thinkbottomup.com.au 的帖子中描述了这一点,标题为C++ Mixins - 通过继承重用是好的......如果以正确的方式完成。
在您的情况下,它看起来像这样:
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;
}
方法2:CRTP!
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;
}
有关这两种解决方案的注意事项:
- 不好奇CRTP如何到处重复出现?:-)
- 出于教学目的,我使用的代码是 C++11,但在 C++98 中也是如此。
不能让类覆盖不相关类的虚函数。您可以采取不同的措施来解决此问题。你可以使mixin成为(虚拟地)派生自类型参数的模板,并将其用作class Example : public virtual Base, Mixin
,或者你可以在最终类中添加代码以调度到混音:
void Derived::test() { Mixin::test(); }
相关文章:
- 虚拟基类函数中派生类的大小
- 无法访问基类函数 C++
- 如何使派生类函数在调用时始终调用相同的基类函数?
- C++虚拟函数:基类函数是调用的,而不是派生的
- Qt基类函数定义
- 添加字符串类型的类成员会导致调用基类函数而不是子函数
- 有没有办法调用基类函数,该函数在使用私有继承的派生类中被覆盖?
- C++ - 基类函数指针调用的替代方法
- 什么更有效率?在重载函数中或通过在基类函数中检查对象类型来实现
- 重载基类函数是不好的做法吗?
- 在 qml 中公开基类函数
- 调用基类函数时强制使用类名?
- 如何判断哪个派生的类对象称为基类函数
- 获取具有基类函数的派生类
- 有没有办法从基类函数参数中推断出模板参数
- 私有非虚拟基类函数被称为派生类中的函数
- 模板基类函数成员的别名
- 如何用相同的签名从main调用基类函数
- C++ 如何从 main 调用派生的基类函数
- memcpy派生类到基类,为什么还调用基类函数