多重继承虚拟调用歧义

时间:2015-07-20 16:34:46

标签: c++ polymorphism multiple-inheritance

手头的问题很难描述,因此为了更清晰起见,代码被放在前面。

struct Base
{
    int b;
    virtual void foo(){cout << b << endl;}
    Base(int x) : b(x){}
};

struct Derived1 : Base    //not virtual
{
    virtual void foo(){/*Derived2's code*/}
    Derived1() : Base(1){}
};

struct Derived2 : Base    //not virtual
{
    virtual void foo(){/*Derived2's code*/}
    Derived2() : Base(2){}
};

struct MultiInheritance : Derived1, Derived2
{
    void bar1()
    {
        //needs to access Derived1's Base foo()
    }
    void bar2()
    {
        //needs to access Derived2's Base foo()
    }
};

假设在一些奇怪的奇怪场景中,我希望基类MultiInheritance有两个基类Derived1Derived2,它们具有共同的非虚拟基类Base

Base中有两个MultiInheritance,如何指定我希望在Base中访问哪个MultiInheritance类?

上面的代码似乎可以通过多次转换来正常工作,但我不确定这是否是已定义的行为。如果是,编译器如何实现多态性的需求呢?一方面virtual调用应该都会产生相同的virtual函数表,但另一方面,如果它发生则不会产生不同的答案。

修改

我想强调Base类必须非虚拟

EDIT2

深深道歉,我严重歪曲自己。上面的代码更新更好地反映了我原来的问题。

3 个答案:

答案 0 :(得分:2)

这被称为钻石问题。

http://www.cprogramming.com/tutorial/virtual_inheritance.html

如果你想保持base non-virtual并获得你现在正在寻找的行为,你可以通过以下方式在MultipleInheritance中执行此操作,以确保从正确的基类调用public class TestMemory { public static void main(String [] args) { int mb = 1024*1024; //Getting the runtime reference from system Runtime runtime = Runtime.getRuntime(); System.out.println("##### Heap utilization statistics [MB] #####"); //Print used memory System.out.println("Used Memory:" + (runtime.totalMemory() - runtime.freeMemory()) / mb); //Print free memory System.out.println("Free Memory:" + runtime.freeMemory() / mb); //Print total available memory System.out.println("Total Memory:" + runtime.totalMemory() / mb); //Print Maximum available memory System.out.println("Max Memory:" + runtime.maxMemory() / mb); } } 函数

foo()

答案 1 :(得分:0)

  

MultiInheritance中有两个Base,如何指定哪个Base   我希望在MultiInheritance中访问哪个类?

您对

中要调用的基础对象存在歧义
void MultiInheritance::bar1(){
     foo();
}

解决这个问题的方法是告诉编译器在哪里寻找foo。

void MultiInheritance::bar1(){
     Derived1::foo();  // The same foo() as in your question.
}

这是您的

所取得的成果
void MultiInheritance::bar1()
{
    Derived1& d = *this;

这在§10.2.12的标准中有所描述。这是明确的定义。

是你的链条
void MultiInheritance::bar1()
{
    Derived1& d = *this;
    Base& b = *this;

同一段。

不幸的是,范围解析运算符无法让您从MultiInhteritance直接跳转到Base

MultiInheritance::foo(){
     Derived1::Base::foo();

描述了嵌套Base

要访问属于Base的foo(),您可以使用MultiInheritance中的范围分辨率语法,以及Derived1和Derived2中的范围分辨率语法。

Derived1()::foo(){
    Base::foo; 

如果这不合适,那么您建议的选项是剩余的选项。

  

如果是,编译器如何实现满足需求   多态性?一方面虚拟呼叫都应该导致   相同的虚函数表,但另一方面,如果它不这样做   输出不同的答案。

编译器实现因编译器而异,并且作为评论者声明:使用vtable进行虚函数是一个实现细节。如果实现使用vtable来实现虚拟功能,则实现需要考虑这种情况。

答案 2 :(得分:0)

这是一个更具说明性的例子。

#include <iostream>
using namespace std;

template <typename Res, typename Arg>
Res& as(Arg& arg)
{
  return arg;
}

struct Base
{
    virtual void foo() = 0;
};

struct Derived1 : Base {};
struct Derived2 : Base {};

struct MoreDerived1 : Derived1
{
    void foo() { cout << "Derived1\n"; }
};

struct MoreDerived2 : Derived2
{
    void foo() { cout << "Derived2\n"; }
};

struct MultiInheritance : MoreDerived1,  MoreDerived2
{
    void bar1() { as<Derived1>(*this).foo(); }
    void bar2() { as<Derived2>(*this).foo(); }
};

int main ()
{
     MultiInheritance m;
     m.bar1();
     m.bar2();
}

这个例子说明了:

  1. 您不需要使用完全继承路径明确指定需要哪个Base,只需转到具有明确Base子对象的子对象
  2. 虚拟功能机制在这里工作。如果您尝试拨打Derived1::foo()
  3. ,则无效

    as辅助函数只是一个语法糖,你也可以说

    Derived1& d = *this;
    d.foo();