C++菱形继承,二义性问题以及解决方法

C++菱形继承,二义性问题

1.菱形继承(路径二义性问题)

在实现继承的过程中,若派生类B,C同时继承基类A,派生类D同时继承类B,C这样对于基类A中的成员相当于在D被继承过两次,A,B,C,D整体关系构建成为一个菱形框图,这样就是C++中的菱形继承问题


代码实现

#include <iostream>
using namespace std;

class A{
public:
    A():a(1)
    {}

    void printf()
    {
        cout << " this s class A " << a << endl;
    }

    int a;
};


class B : public A{

};

class C : public A{

};

class D : public B, public C{

}; 

int main(void)
{
    D d;
    d.printf();
    d.a = 10;
    d.printf();
    return 0;
}

编译结果为 :

Daimo.cpp: In function 'int main()':
Daimo.cpp:33: error: request for member 'printf' is ambiguous//混淆的,模糊不清的
Daimo.cpp:9: error: candidates are: void A::printf()
Daimo.cpp:9: error:                 void A::printf()
Daimo.cpp:34: error: request for member 'a' is ambiguous
Daimo.cpp:14: error: candidates are: int A::a
Daimo.cpp:14: error:                 int A::a
Daimo.cpp:35: error: request for member 'printf' is ambiguous
Daimo.cpp:9: error: candidates are: void A::printf()
Daimo.cpp:9: error:                 void A::printf()

编译结果发生错误, 在使用派生类D的实例化对象d中所调用基类A的成员时,编译器无法通过编译

接下来看一下类A,B,C,D的大小分别为多少

[centos6@bogon Test]$ cat Daimo.cpp 
#include <iostream>
using namespace std;

class A{
public:
    A():a(1)
    {}

    void printf()
    {
        cout << " this s class A " << a << endl;
    }

    int a;
};


class B : public A{

};

class C : public A{

};

class D : public B, public C{

}; 

int main(void)
{
    A a;
    cout<<" Size of class A : "<<sizeof(a)<<endl;
    B b;
    cout<<" Size of class B : "<<sizeof(b)<<endl;
    C c;
    cout<<" Size of class C : "<<sizeof(c)<<endl; 
    D d;
    cout<<" Size of class D : "<<sizeof(d)<<endl; 
    return 0;
}
[centos6@bogon Test]$ ./a.out 
 Size of class A : 4
 Size of class B : 4
 Size of class C : 4
 Size of class D : 8

可见A,B,C的大小都为4 ,而由于类D继承了两次,它的大小为八个字节(因为相当于继承了两个A,所以大小是A的两倍)


对于菱形继承问题的解决方法
  • 使用时添加作用域
//例如在类D的实例化对象d中,在调用路径冲突的A成员时加上作用域的限定
d.B::function();
d.C::function();
  • 使用虚基类
    在继承的时候采用虚基类继承 关键字 virtual
#include <iostream>
using namespace std;

class A{
public:
    A():a(1)
    {}

    void printf()
    {
        cout << " this s class A " << a << endl;
    }

    int a;
};


class B : virtual public A{

};

class C : virtual public A{

};

class D : public B, public C{

}; 

int main(void)
{
    D d;
    d.printf();
    d.a = 10;
    d.printf();
    return 0;
}

2.同名二义性问题

在多重继承中,类A为基类,B为基类,C为A,B的派生类,而且A,B中有同名的成员(成员函数或者成员变量),在访问时访问时发生二义性冲突
代码实现

#include <iostream>
using namespace std;

class A {
public:
    void function()
    {
        cout << "this is class A : " << this << endl;
    }
};

class B {
public:
    void function()
    {

        cout << "this is class B : " << this << endl;
    }
};

class C : public B,public A {

};

int main()
{
    C c;
    c.function();
    return 0;
}

编译结果(发生同名二义性问题)

[centos6@bogon Test]$ g++ Daimo.cpp 
Daimo.cpp: In function 'int main()':
Daimo.cpp:28: error: request for member 'function' is ambiguous
Daimo.cpp:6: error: candidates are: void A::function()
Daimo.cpp:14: error:                 void B::function()
Daimo.cpp: At global scope:
Daimo.cpp:30: error: expected constructor, destructor, or type conversion at end of input

解决方法

  • 上述的采用作用域的相同方法
  • 在c中用接口函数覆盖完成对类A,B成员的调用

猜你喜欢

转载自blog.csdn.net/liu_zhen_kai/article/details/81590467
今日推荐