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成员的调用