基类派生自同一类的 C++ 多重继承 [英] C++ multiple inheritance with base classes deriving from the same class

查看:19
本文介绍了基类派生自同一类的 C++ 多重继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试重用来自不同类的代码时偶然发现了一个问题.我把它贴在这里希望你们中的一些人可以帮助我.

I have stumbled on a problem while trying to re-use code from different classes. I post it here in hope that some of you might be able to help me.

我有一组派生自同一个类 (A) 的类 (B,C),它们强制执行某些方法 (foo, run).B 类实现了这些方法,B 类和 C 类都提供了其他方法:

I have a set of classes (B,C) deriving from the same class (A) which forces the implementation of some methods (foo, run). Class B implements these method, and both B and C provide other methods:

#include<iostream>

template<class I, class O>
class A {
public:
    A() {}
    virtual ~A() {}

    virtual void foo() const = 0;     // force implementation of this function
    virtual void run() const = 0;     // force implementation of this function
};

template<class I, class O>
class B : public A<I,O> {
public:
    B() {}
    virtual ~B() {}

    virtual void foo() const {        // implementation for the Base class
        std::cout << "B's implementation of foo" << std::endl;
    }

    virtual void run() const {        // implementation for the Base class
        std::cout << "B's implementation of run" << std::endl;
    }

    virtual void foobar() const {     // some other function provided by this class
        std::cout << "B's implementation of foobar" << std::endl;
    }
};

template<class I, class O, class M>
class C : public A<I,O> {
public:
    C() {}
    virtual ~C() {}

    virtual void bar(M m) const {     // some other function provided by this class
        std::cout << "C's implementation of bar with: " << m << std::endl;
    }
};

现在,我想做的是从 B 和 C 继承,这样我就可以有额外的方法 (foobar, bar),但也不必实现类 A (foo) 中的方法,因为它已经是在 B 中定义:

Now, what I am trying to do is inherit from both B and C so that I can have the extra methods (foobar, bar), but also not have to implement the method from class A (foo) because it is already defined in B:

template<class I, class O>
class D : public B<I,O>, public C<I,O,int> {
public:
    D() {}

    void run() const {
        this->bar(123);
        this->foo();
        this->foobar();
    }
};

但由于某种原因,编译器给了我这个错误:

But for some reason the compiler gives me this error:

test.cpp: 在函数‘int main(int, char**)’中:test.cpp:68:35: 错误:无法分配抽象类型D"的对象

test.cpp: In function ‘int main(int, char**)’: test.cpp:68:35: error: cannot allocate an object of abstract type ‘D<float, double>’

A<float, double>*d = new D();//我需要做什么

A<float, double> *d = new D<float, double>(); // what I need to do

test.cpp:48:11:注意:因为以下虚函数在‘D’中是纯的:

test.cpp:48:11: note: because the following virtual functions are pure within ‘D<float, double>’:

D类:公共B<I,O>,公共C<I,O,int>{

class D : public B<I,O>, public C<I,O,int> {

    ^

test.cpp:9:22: 注意:void A<I, O>::foo() const [with I = float;O = 双倍]

test.cpp:9:22: note: void A<I, O>::foo() const [with I = float; O = double]

虚空 foo() const = 0;//强制执行这个函数

virtual void foo() const = 0; // force implementation of this function

这是我用来运行它的代码:

This is the code I use to run it:

int main(int argc, char **argv)
{

    A<float, double> *b = new B<float, double>();
    b->foo();                                            // prints "B's implementation of foo"
    b->run();                                            // prints "B's implementation of run"

    //A<float, double> *c = new C<float, double, int>(); // obviously fails because C does not implement any of A's functions

    //A<float, double> *d = new D<float, double>;        // line 68: what I need to do
    //d->run();                                          // ***throws the abstract class error

    return 0;
}

我想从指向 A 的指针使用 D 类对象的运行"函数.由于所有函数都是虚拟的,我希望执行在最低继承点中定义的每个函数的实现,这意味着B"::run' 将被丢弃.由于 'D::run' 使用来自 B 和 C 的函数,我需要从这两个类中继承.

I want to use the 'run' function of an object of class D from a pointer to a A. As all the functions are virtual I expect to execute implementation of each function defined in the lowest inheritance point, meaning that 'B::run' will be discarded. As 'D::run' uses functions from both B and C I need to inherit from both classes.

我希望我已经对它进行了足够的描述并且不会混淆任何人.感谢您的帮助!

I hope I have described it enough and not confused anybody. Thanks for the help!

推荐答案

如果将 BC 更改为虚拟继承 A模板类,当被 D 组合时,它们将共享一个基实例,并且此错误将消失:

If you change B and C to virtually inherit from the A template class, they will share a single base instance when combined by D and this error will go away:

template<class I, class O>
class B : virtual public A<I,O> {

// ...

template<class I, class O, class M>
class C : virtual public A<I,O> {

然而,这种模式(称为菱形继承(反)模式)可能很难推理,我强烈建议尽可能避免它.以后您可能会遇到更加晦涩难懂的问题.

However, this pattern (known as the diamond inheritance (anti-)pattern) can be very difficult to reason about and I would strongly suggest avoiding it if possible. You are likely to run into even more obscure problems later.

以下是此技术工作的示例,但显示了一些乍一看可能出乎意料的结果:

Here is a sample of this technique working, but showing some results that may not be expected at first glance:

class A {
public:
    virtual void foo() = 0;
};

class B : virtual public A {
public:
    virtual void foo() override;
};

void B::foo()
{
    std::cout << "B::foo()" << std::endl;
}

class C : virtual public A { };

class D : public B, public C { };

int main() {
    D d;
    C & c = d;

    c.foo();

    return 0;
}

请注意,即使您调用的是纯虚函数 C::foo(),由于只有一个 A 实例,继承的纯虚函数解析为B::foo() 虽然共享 A 虚表.这是一个有点令人惊讶的副作用 -- 您可以最终调用在表亲类型上实现的方法.

Note that even though you are calling C::foo(), which is pure virtual, since there is only one A instance the inherited pure virtual function resolves to B::foo() though the shared A vtable. This is a somewhat surprising side-effect -- that you can wind up invoking methods implemented on a cousin type.

这篇关于基类派生自同一类的 C++ 多重继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆