c++ - 如何覆盖另一个基类中的函数?

标签 c++ inheritance multiple-inheritance mixins

我不太确定要使用的术语,但这是我的示例:

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,但在我的例子中有几个派生类,它们没有共同的祖先。

最佳答案

您不能直接让类重写不是其基类的方法。但是你可以用一种迂回的方式来做。我将介绍两种这样的方法 - 我更喜欢第二种。

方法一

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!

CRTP是“Curiously Recurring Template Pattern”——如果你以前没见过它,一定要点击那个链接。通过这种方法,我们将使用 virtual 继承说明符来避免歧义,并且与之前的方法不同 - 我们不会颠倒 Mixin示例 类。

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。

关于c++ - 如何覆盖另一个基类中的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19528338/

相关文章:

c++ - 在单独的函数中创建一个动态数组并通过调用函数对其进行操作

c++ - C++中有序树的良好节点定义

C++,不能实例化抽象类

C++ 继承简单错误

c++ - ThreadPool - 如何在其成员线程完成后删除 Worker (this)

c++ - 如何使用 C++ 在 QT 中的 QInputDialog 中隐藏 "Cancel"按钮?

Java静态变量值不能传递

c# - Entity Framework 继承和持久化列

c++ - 一道C++接口(interface)(纯虚类)/多重继承/虚继承的设计题

c++ - 虚拟继承的其他替代方案?