一、多继承同名覆盖
子类中的成员与父类中的成员同名问题,通过作用域分辨符(::)进行限定类的访问,从而实现对不同类中的同名成员各自赋值。
#include<iostream>
using namespace std;
class A{//父类A public:int val;void fun(){cout<<"Member of A,val值为:"<<val<<endl; }
};
class B{//父类B:两父类的成员名相同 public:int val;void fun(){cout<<"Member of B,val值为:"<<val<<endl; }
};
class C:public A,public B{//继承父类AB且成员名与父类的成员名相同 public:int val;void fun(){cout<<"Member of C,val值为:"<<val<<endl;}
};
int main()
{C c;c.val=1;//访问C类中的val变量 c.A::val=2;//通过作用域分辨符(::)限定访问成员的类 c.B::val=3;//限定访问B类中的val变量 c.fun();c.A::fun();//限定访问A类中的fun方法 c.B::fun(); }
运行结果
二、多层多继承二义性问题
多层继承:
#include<iostream>
using namespace std;
class A{public:int val;void fun(){cout<<"Member of A,val="<<val<<endl;}
};
class B:public A{//B继承A public:int val1;
};
class C:public A{//C继承Apublic:int val2;
};
class D:public B,public C//D继承B、C: 类D拥有两份在不同类下的同名拷贝
//二义性问题:对同一成员不同数据的多份拷贝,同一成员拥有不同数据
{public:int val3;
};
int main()
{D d;d.B::val=3;//D中有两份不同的val与fun数据 d.C::val=5;d.B::fun();d.C::fun();
}
运行结果
出现二义性问题,即A类的同名成员有两份数据保存在内存中,为解决该问题,我们引入虚基类来标识其共同基(共同父类)来实现。
改进:将共同基(共同父类)定义为虚基类
#include<iostream>
using namespace std;
class A{public:int val;void fun(){cout<<"Member of A,val="<<val<<endl;}
};
class B:virtual public A{//B继承A public:int val1;
};
class C:virtual public A{//C也继承A:将两者共同父类设为虚基类,可实现同名成员在内存中只有一份拷贝 public:int val2;
};
class D:public B,public C{public:int val3;
};
int main()
{D d;d.B::val=3;d.C::val=5;//新赋的值会覆盖原来赋的值,val变量在内存中只会有一个值 d.B::fun();d.C::fun();d.fun(); }
运行结果
通过虚基类实现同名成员的同一赋值。
三、赋值兼容性规则问题
赋值的单向性规则:
1.子类对象赋值给父类
2.子类对象初始化父类引用
3.子类对象地址赋给父类指针,且此时父类指针只能调用父类中的方法。
#include<iostream>
using namespace std;
class A{protected: int x;public:A(int x1=0):x(x1){}void print(){cout<<"A类中x="<<x<<endl;}
};
class B:public A{int y;public:B(int x1=0,int y1=0):A(x1){//子类B初始化父类A的引用y=y1;}void print(){cout<<"B类中x="<<x<<"\ty="<<y<<endl;}
};
class C:public A{int z;public:C(int x1=0,int z1=0) :A(x1){//子类C初始化父类A的引用 z=z1;}void print(){cout<<"C类中x="<<x<<"\tz="<<z<<endl;}
};
int main()
{A a(2);B b(3,4);//子类b对象将3赋值给A类中的x成员 C c(5,6);//子类c对象将5赋值给A类中的x成员 A *p[3]={&a,&b,&c};//定义父类A的指针,分别装B,C对象的地址 for(int i=0;i<3;i++)p[i]->print();//只能调用父类中的方法 b.print();c.print();}
运行结果