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

查看:176
本文介绍了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.

我有一组来自同一个班级的班级(B,C)(A )强制执行某些方法(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< float,double>'

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< float,double>(); //我需要做什么

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

test.cpp:48:11:注意:因为以下虚拟函数在'D<内是纯粹的; float,double>':

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


class D:public B< I,O> ;, public 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 = double]

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


virtual void 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;
}

我想使用D类对象的'run'函数指向A的指针。由于所有函数都是虚函数,我希望执行在最低继承点中定义的每个函数的实现,这意味着将丢弃'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!

推荐答案

如果您更改 B C 实际上从 A 模板类继承,当它们由<$组合时,它们将共享一个基本实例c $ c> 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 vtable。这是一个有点令人惊讶的副作用 - 您可以最终调用在表兄弟类型上实现的方法。

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天全站免登陆