C++的多重继承和纯函数

C++ multiple inheritance and pure functions

本文关键字:函数 多重继承 C++      更新时间:2023-10-16

我对"多重继承问题"有点困惑。考虑以下大块代码:

#include <iostream>
struct iface
{
    virtual void foo () = 0;
    virtual ~iface () {}
};
struct wrapped
{
    virtual void foo ()
    {
        std::cerr << "wrappedn";
    }
};
struct impl : public wrapped, public iface
{
};
iface* factory ()
{
    return new impl;
}
int main ()
{
    iface *object = factory ();
    object->foo();
    delete object;
    return 0;
}

这是从一些使用皮条客习语的代码中抽象出来的。这个想法是wrapped是一个复杂的类,有各种其他的铃铛和口哨。iface只是使wrapped的一个特定方面可见,而factory()函数通过使用wrapped构建了一个实现ifaceimpl类。在我的实际代码中,wrapped类来自一个具有巨大头树的库,因此我在一个单独的编译单元中定义impl,以避免我的应用程序的其他部分不得不将它们拉入

无论如何,我粘贴的内容不会编译,并给出以下错误:

$ g++ -o test test.cc
test.cc: In function ‘iface* factory()’:
test.cc:23:16: error: cannot allocate an object of abstract type ‘impl’
     return new impl;
                ^
test.cc:17:8: note:   because the following virtual functions are pure within ‘impl’:
 struct impl : public wrapped, public iface
        ^
test.cc:5:18: note:     virtual void iface::foo()
     virtual void foo () = 0;
                  ^

显然,我可以通过在impl中编写foo的具体实现来避免错误,该实现转发到wrapped::foo(),但我不明白编译器为什么不从wrapped类中获取实现。

我假设iface中的"foo"和wrapped中的"foo"在为impl进行名称解析(这个词对吗)时会有所不同,但我真的不明白为什么。

有人能解释一下发生了什么吗?

如果一个类的任何虚拟函数都是纯虚拟的,那么该类就是absrtract。类impl有两个名称相同的成员函数

iface::foo

wrapped::foo

类impl的第一个成员函数是纯虚拟的,因此类是抽象的。编译器不能创建抽象类的对象。

impl有两个完全独立的方法,即纯的iface::foowrapped::foo。没有名称解析——虚拟函数调用由一个名为vtable的结构调度,该结构保存指向实现的指针。一个类的每个直系祖先都有单独的vtable,至少在没有虚拟继承的情况下是这样。来自不同祖先的同义虚拟函数最终出现在不同的vtable中;编译器无法"组合"它们。C++没有mixin。

显然,我可以通过在impl中编写foo的具体实现来避免错误,该实现将转发到wrapped::foo()

更好的是,不要使用双重继承——做一些类似的事情

struct impl : public iface
{
    virtual void foo ()
    {
        wr.foo ();
    }
private:
    wrapped wr;
};