C++名字冲突问题:
什么是C++的名字冲突,假如一个子类继承基类,基类中有相同的成员变量和成员函数名,这样在子类对象调用中就存在歧义,这就是名字冲突,解决办法就是使用作用域限定符指明基类中成员属于谁,具体代码如下:
#include <iostream>
using namespace std;
class A {
public:
int m_data;
void foo(void){
cout<<m_data<<endl;
}
};
class B{
public:
float m_data;
void foo(int var){
cout<<m_data<<endl;
}
};
class C:public A,public B{
};
int main(void){
C c;
c.A::m_data =10;//指明是谁的成员
c.B::m_data =1.2;
c.A::foo(); //指明是谁的函数
c.B::foo(1);
return 0;
}
虚拟继承解决钻石继承的不足:
所谓的钻石继承,就是基类中的继承就沿着多条不同的路,基类中的数据就会有多份不同的拷贝。你从多处访问时就会有不一致现象,会出现问题。
#include <iostream>
using namespace std;
class A{
public:
A(int data):m_data(data){}
int m_data;
};
class B:public A{
public:
B(int data):A(data){}
void set(int data){
m_data= data;
}
};
class C:public A{
public:
C(int data):A(data){}
int get(void){
return m_data;
}
}
class D:public B,public C{
public:
D(int data):B(data),C(data){}
};
int main(void){
D d(1000);
d.set(2000);
cout<<d.get()<<endl;//?1000
return 0;
}
为什么打印出来的值是1000呢?
首先A B C D的继承关系如图,A在B,C中都有一份,m_data初始值都为1000;但是调用set的时候只是将B中的m_data变为2000;C中的m_data还是为1000,然后调用C中的get得到的值当然就是1000了;
其实理想的状态应该是这样的:A的数据在B和C中共享,有点类似共享内存呢?
那么我们怎么做到呢,现在就要用到虚继承,将上面代码修改如下:
#include <iostream>
using namespace std;
class A{
public:
A(int data):m_data(data){}
int m_data;
};
class B:virtual public A{ //增加virtual
public:
B(int data):A(data){}
void set(int data){
m_data= data;
}
};
class C:virtual public A{ //增加virtual
public:
C(int data):A(data){}
int get(void){
return m_data;
}
}
class D:public B,public C{
public:
D(int data):B(data),C(data),A(data){} //对A进行构造
};
int main(void){
D d(1000);
d.set(2000);
cout<<d.get()<<endl;//?2000
return 0;
}