第七章派生与继承2/*7.4多继承与虚基类7.4.1多继承中的二义性问题解决方式1<对象名>.<基类名>::<成员名> //数据成员<对象名>.<基类名>::<成员名>(<参数名>) //成员函数*//*#include<iostream>using namespace std;class Base1{public:int date;void fun(){cout<<"Member of Base1"<<";base1="<<date<<endl;} };class Base2{public:int date;void fun(){cout<<"Member of Base2"<<";base2="<<date<<endl;} };class Derived:public Base1,public Base2{public:int date;void fun(){cout<<"Member of Derived"<<";Derived="<<date<<endl;} };int main(){Derived obj;obj.date=1;obj.fun();obj.Base1::date=2;obj.Base1::fun();obj.Base2::date=3;obj.Base2::fun();return 0;}*//*#include <iostream>using namespace std;class Base{public:int date;void fun(){cout<<"This is Base"<<"; base="<<date<<endl;}};class Derived11:public Base{public:int date;void fun(){cout<<"This is Derived11"<<"; Derived11="<<date<<endl;}};class Derived12:public Base{public:int date;void fun(){cout<<"This is Derived12"<<"; Derived12="<<date<<endl;}};class Derived2:public Derived11,public Derived12{public:int date;void fun(){cout<<"This is Derived2"<<"; Derived2="<<date<<endl;}};int main(){Derived2 obj;obj.date=1;obj.fun();//obj.Base::date=2;//obj.Base::fun();obj.Derived11::date=3;obj.Derived11::fun();obj.Derived12::date=4;obj.Derived12::fun();return 0;}*//*7.4.2虚基类的定义虚基类格式:class<类名>:virtual<继承方式><基类名>virtual与继承方式的位置无关,但是必须位于虚基类之前,切只对紧后面的基类名起作用。
7.4.3虚基类的构造函数由于派生类的对象中只有一个虚基类对象,所以在建立一个派生类的对象时,为保证虚基类对象只被初始化一次。
这个虚基类构造函数只能被调用一次,当在构造函数的初始化列表中同时出现对虚基类和非虚基类构造函数的调用时虚基类的构造函数先于非基类的构造函数被调用;*//* #include<iostream>using namespace std;class Base{public:Base(char i){cout<<"Base'scons"<<i<<endl;}~Base(){cout<<"Base'sdes."<<endl;}private:// char c;};class Derived11:virtual public Base{public:Derived11(char i,char j):Base(i){cout<<"Derived11's cons"<<j<<endl;} ~Derived11(){cout<<"Derived11's des."<<endl;}private://char b;};class Derived12:virtual public Base{public:Derived12(char i,char j):Base(i){cout<<"Derived12's cons"<<j<<endl;} ~Derived12(){cout<<"Derived12's des."<<endl;}private://char f;};class Derived2:public Derived11,public Derived12{public:Derived2(char i,char j,char k,char l,char m,char n):Derived12(k,l),Derived11(i,j),Base(i),aa(m){cout<<"Derived2's cons"<<n<<endl;}~Derived2(){cout<<"Derived2's des."<<endl;}private:Base aa;};int main(){ Derived2 obj('a','b','c','d','e','f');return 0;}*//*7.5子类型关系1.子类型关系可以传递但不可逆,公有继承可以实现子类型关系,通过公有继承,派生类得到了基类的除了构造函数析构函数之外的所有成员。
所以派生类对象就可以作为基类的对象使用,但是他只能使用从基类继承的成员,2.具有子类型关系的基类和平派生类的对象之间满足如下赋值兼容规则。
(1)公有派生类的对象可以赋值给基类的对象,即公有派生类对象中从基类继承来的成员。
(2)公有派生类的对象可以初始化基类的引用(3)公有派生类的地址可以赋值给指向基类的指针。
*//*#include <iostream>using namespace std;class Base{public :void Who(){cout<<"class Base. "<<endl;}};class Derived1:public Base{public :void Who(){cout<<"class Derived1. "<<endl;}};class Derived2:public Base{public :void Who(){cout<<"class Derived2. "<<endl;}};int main(){Base obj1,*p;Derived1 obj2;Derived2 obj3;p=&obj1;p->Who();p=&obj2;p->Who();p=&obj3;p->Who();obj2.Who();obj3.Who();return 0;}*//*7.6虚函数与多态性一个面向对象的系统常常要求一组具有基本语义的方法能在同意接口下为不同的对象服务,这就是多态性多态性分为编译多态性和运行多态性7.6.2虚函数1,在非静态成员函数声明前加virtual就叫虚函数。
2,在派生类中重定义虚函数时,函数名,形参表和返回值类型必须保持不变。
3,虚函数在派生类中被定义后,仍是虚函数,在派生类中再次被定义后还是虚函数,不管是否加了virtual 4,对虚函数的调用分多态调用和非多态调用多态调用是指借助于指针和引用的调用,非多态调用是指不借助于指针和引用的调用,通过成员访问运算符"." 进行的。
对实函数的任何形式的调用都是非多态的。
下面是如何实现动态绑定机制的*//*#include<iostream>using namespace std;class Base{char base_name[10];public:Base(){strcpy (base_name,"BASE");}virtual char * my_name(){return base_name;}char * class_name(){return base_name;}};class Derived:public Base{char derived_name[10];public:Derived(){strcpy(derived_name,"DERIVED");}virtual char * my_name(){return derived_name;}char * class_name(){return derived_name;}};void show_ptr(Base *p){cout<<endl<<p->my_name()<<" "<<p->class_name();}void show_ref(Base &r){cout<<endl<<r.my_name()<<" "<<r.class_name();}int main(){Base bb;Derived dd;cout<<endl;show_ptr(&bb);cout<<"<==应该显示'BASE BASE'"; show_ptr(&dd);cout<<"<==应该显示'DERIVED BASE'"; cout<<endl;show_ref(bb);cout<<"<==应该显示'BASE BASE'";show_ref(dd);cout<<"<==应该显示'BASEDERIVED BASE'";cout<<endl;cout<<endl<<bb.Base::my_name()<<""<<bb.Base::class_name();cout<<"<==应该显示'BASE BASE'";cout<<endl<<dd.Base::my_name()<<""<<dd.Base::class_name();cout<<"<==应该显示'BASE BASE'";return 0;} *//*7.6.3虚析构函数只要派生类这种对析构函数进行了专门的定义,其基类的析构函数就应该声明为虚析构函数。