📄 ex22.cpp
字号:
//第22章 多重继承和类型变换
//[例22.1]多个直接基类
#include<stdio.h>
struct CBase1
{ CBase1(int n=1){m_b1=n;printf("CBase1::CBase1()this=%p,%p\n",this,&m_b1);}
void Show()
{printf("%d.CBase1::Show() sizeof(CBase1)=%d\n",m_b1,sizeof(CBase1));}
int m_b1;
};
class CBase2
{ public: CBase2(int n=2)
{m_b2=n;printf("CBase2::CBase2()this=%p,%p\n",this,&m_b2);}
void Show()
{printf("%d.CBase2::Show() sizeof(CBase2)=%d\n",m_b2,sizeof(CBase2));}
long l;
protected: int m_b2;
};
class CDerived:public CBase2, virtual public CBase1
{ public:CDerived(int n=3)
{m_d=n;printf("CDerive::CDeriv this=%p,%p\n",this,&m_d);}
int m_d;
int Show();
};
int CDerived::Show()
{ CBase1::Show(); CBase2::Show();
printf("%d.CDerived::Show() sizeof(CDerived)=%d\n",m_d,sizeof(CDerived));
return 0;
}
void main() { CDerived d; d.Show(); }
//[例22.2]关键字virtual对多重继承的影响。从输出结果注意构造函数调用的次序。
#include<stdio.h>
class CTop
{ public: int mt;
CTop(int n=0) {mt=n;printf("%d.CTop()this=%p,%p\n",mt,this,&mt);}
};
struct CBase1:virtual public CTop
{ CBase1(int n=1) {b1=n;printf("CBase1()this=%p,%p\n",this,&b1);}
void Show()
{printf("%d.CBase1::Show()sizeof(CBase1)=%d\n",b1,sizeof(CBase1));}
int b1;
};
class CBase2: public virtual CTop
{ public: CBase2 (int n=2){b2=n;printf("CBase2()this=%p,%p\n",this,&b2);}
void Show()
{printf("%d.CBase2::Show()sizeof(CBase2)=%d\n",b2,sizeof(CBase2));}
long l; protected: int b2;
};
class ClassD:public CBase1,public CBase2
{ public: int d;
ClassD(int n=3){d=n;printf("ClassD()this=%p,%p\n",this,&d);}
int Show();
};
int ClassD::Show()
{ CBase1::Show(); CBase2::Show();
printf("%d.ClassD::Show()sizeof(ClassD)=%d\n",d,sizeof(ClassD));
return 0;
}
void main() { ClassD d; d.Show(); }
//[例22.3]非虚拟继承两个基类同时包含两个嵌入对象的派生类
#include <stdio.h> //先调用基类的构造函数然后调用派生类嵌入对象的构造函数。
struct A { A(int n=1){printf("A=%d,",n);}}; //首先根据声明的次序分别调用
struct B { B(int n=2){printf("B=%d,",n);}}; //基类A,B的构造函数
struct D:public A,public B //基类构造函数的次序为A,B
{ D(int n,int m): A(n),b(m) //构造函数定义, 仅显式调用A(n),b(m)
{printf("D=%d\n",n+m);}//包容类D的构造函数后于嵌入对象的构造函数被调用
B b; A a; //声明两个嵌入结构变量,次序为b,a
}; //嵌入对象构造函数的调用次序为B,A
void main(){ D d(100,200);} //输出:A=100,B=2,B=200,A=1,D=300
//[例22.4]多继承间接基类的初始化
#include<stdio.h>
class CTop //虚拟继承的树层次//
{ public: int m_t;
CTop(int n=0)
{ m_t=n; printf("%d.CTop=%d,",m_t,sizeof(CTop));}
};
struct CBase1:virtual public CTop
{ int m_b1;
CBase1(int n=1):CTop(n)
{ m_b1=n;printf("%d.CBase1=%d,",m_b1,sizeof(CBase1));}
}; class CBase2: public virtual CTop { public: CBase2 (int n=2):CTop(n) { m_b2=n; printf("%d.CBase2=%d,",m_b2,sizeof(CBase2));} protected: int m_b2; }; class CDerived:public CBase1,public CBase2 { public:
CDerived(int n):CBase2(n-3),CBase1(n-2),CTop(n-1)//构造函数初始化
{m_d=n; printf("%d.CDerived=%d\n",m_d,sizeof(CDerived));}
int m_d;
};
void main() {CDerived d(4) ; }
CDerived(int n):CBase2(n-3),CBase1(n-2)
{m_d=n; printf("%d.CDerived=%d\n",m_d,sizeof(CDerived));}
//[例22.5]不唯一的名称m_n,Set,f()可产生二义性。
#include<stdio.h>
class A { public: void f(){} }; class B:public A{ public : void f(){}
public : int m_n; void Set(int n){ m_n=n; } };
struct C { int m_n; void Set(int n){m_n=n; } };
class D:public C,public B
{ public: int m_d; void Set(int n){m_d=n;} };
//[例22.6]清除名称二义性的途径
class CTop { public: int m_t; };
struct CBase1: public CTop {int m_b1;};
class CBase2: public CTop {protected: int m_b2; };
class CDerived:public CBase1,public Cbase2
{ public: int m_d; };
//[例22.7]动态类型变换
#include <stdio.h>
class ClassB
{ public: long m_n;
public: ClassB() {m_n=1;}
virtual f(){} //设置一个虚函数是必要的
void Show(){printf("ClassB::m_n=%d\t",m_n);} //此时Show不是虚函数
};
class ClassC:public ClassB
{ public: ClassC() {m_n=2;}
void Show(){printf("ClassC::m_n=%d\t",m_n);}
};
class ClassD:public ClassC
{ public:ClassD() {m_n=3;}
void Show(){printf("ClassD::m_n=%d\t",m_n);}
};
void fcast(ClassB* pObj)
{ ClassC* pObjc=dynamic_cast<ClassC*>(pObj) ;
if(pObjc!=NULL) pObjc->Show();
}
void main()
{ ClassB objb; fcast(&objb);
ClassB *pObjb=new ClassD();//pObjb具有动态类型为ClassD*
fcast(pObjb);
((ClassD*)pObjb)->Show(); //将pObjb真正变换到原来的对象地址
ClassC objc; fcast(&objc);
} //输出:ClassC::m_n=3 ClassD::m_n=3 ClassC::m_n=2
//[例22.8]引用形式的动态类型变换
#include <stdio.h>
#include<typeinfo.h>
class ClassB
{ public: long m_n;
public: ClassB() {m_n=1;}
virtual void Show(){printf("ClassB::m_n=%d\n",m_n);} //该题Show是虚函数
};
class ClassC:public ClassB
{ public: ClassC() {m_n=2;}
void Show(){printf("ClassC::m_n=%d\n",m_n);}
};
class ClassD:public ClassC
{ public:ClassD() {m_n=3;}
void Show(){printf("ClassD::m_n=%d\n",m_n);}
~ClassD() {printf("~ClassD;\n");}
};
void fcast(ClassB& rObj)
{ try{
ClassC& rObjc=dynamic_cast<ClassC&>(rObj) ;
rObjc.Show();
}
catch(bad_cast) { printf("bad_cast produced\n"); }
}
void main()
{ ClassB objb; fcast(objb); //程序输出结果:
ClassB* pObjb=new ClassD(); //bad_cast produced
fcast(*pObjb); //动态绑定发生作用 // ClassD::m_n=3
((ClassD&)*pObjb).Show(); //ClassD::m_n=3
ClassC objc; // ClassC::m_n=2
fcast(objc); // ~ClassD;
delete (ClassD*)pObjb;
}
//[例22.9]继承层次的静态类型变换
#include <stdio.h>
class ClassB
{ public: long m_n;
public: ClassB() {m_n=1;}
//virtual // 去掉双斜杠Show()为虚函数
void Show(){printf("ClassB::m_n=%d\n",m_n);}
};
class ClassC:public ClassB
{ public: ClassC() {m_n=2;}
void Show(){printf("ClassC::m_n=%d\n",m_n);}
};
class ClassD:public ClassC
{ public:ClassD() {m_n=3;}
void Show(){printf("ClassD::m_n=%d\n",m_n);}
~ClassD() {printf("~ClassD;\n");}
};
void fcastb(ClassB& rObj,int n)
{ if(n==1) { ClassC& rObjc=static_cast<ClassC&>(rObj) ;//引用变换语法
rObjc.Show(); }
else { ClassC& rObjc=(ClassC&)(rObj) ; //C形式的变换格式
rObjc.Show(); }
} //上面if分支两种变换格式效果是等价的
void fcasta(ClassB* pObj,int n) //下面if分支两种变换格式效果是等价的
{ ClassC* pObjc;
if(n==1) pObjc=static_cast<ClassC*>(pObj) ; //指针变换语法
else pObjc=(ClassC*)(pObj) ; //C形式的转换格式
pObjc->Show();
}
void fa() //显示指针类型静态变换
{ ClassB objb; fcasta(&objb,1);
ClassB* pObjb=new ClassD(); fcasta(pObjb,1);
ClassC objc; fcasta(&objc,1);
delete (ClassD*)pObjb;
}
void fb() //显示引用形式静态类型变换
{ ClassB objb; fcastb(objb,1);
ClassB* pObjb=new ClassD(); fcastb(*pObjb,2);
ClassC objc; fcastb(objc,1);
}
void main(){ fa(); fb(); }
//[例22.10]简单变量的静态类型变换
#include <stdio.h>
void f(short v) { printf("%d\t",v);}
void f(float f) { printf("%f\n",f);}
void main()
{ long l=10; double d=20;
f( static_cast<short>(l));
f( static_cast< float >(d));
} //程序输出结果:10 20.000000
//[例22.11]简单变量的指针和引用变换
#include <stdio.h>
void f(short& v) { printf("%d\t",v);}
void f(double* p) { printf("%f\t",*p);}
void main()
{ long l=10; float tf=20.0f;
f(reinterpret_cast<short&>(l));
f(reinterpret_cast<double*>(&tf));
f((short&)l); printf("*((double*)&tf)=%f\t",*((double*)&tf));
f((double*)(&tf));
}//////////////程序运行输出结果://///////////////////
//[例22.12]松动实参const属性的变换
#include <stdio.h>
void fc(int* p) { printf("%d\t",*p);}//函数中没有改变间接变量的值
void fc(int& v) { printf("%d\n",v);} // 函数中v作为右值出现
void main() //d具有const int型的类型属性
{ const int d=20;// &d的地址具有const int *型的类型属性
fc( const_cast<int*>(&d)); //效果上等价于fc( (int*)&d);
fc( const_cast<int&>(d)); //效果上等价于fc( (int&)d);
} //输出结果:20 20
//[例22.13]typeid显示表达式的类型信息
#include <stdio.h>
#include<typeinfo.h>
class ClassB //多态类之根基类
{ public: virtual void SetB(){m_b=1;}
int m_b;
};
class ClassC : public ClassB //多态类继承体系之派生类
{ public: void SetB(){m_c=2;} int m_c; };
void main()
{ double d;
if(typeid(int) !=typeid(double*))
if(typeid(&d) ==typeid(double*)) printf("%s\t", typeid(double*).name());
if(typeid('1')==typeid(char)) printf("%s\t", typeid('1').name());
long n;
float& rn=(float&)n; //内置数据变量不进行动态类型跟踪
printf("%s,\t%s\t", typeid(n).name(),typeid(rn).name());
ClassB b; ClassC c;
ClassB& rb=c; //引用rb的动态类型为 class ClassC
printf("%s,\t%s\t", typeid(b).name(),typeid(rb).name());
}//输出:double* char long, float class ClassB, class ClassC
//[例22.14]before和raw_name()成员函数
#include <stdio.h>
#include<typeinfo.h>
#include<string.h>
class ClassB
{ public: virtual void SetB(){m_b=1;}
int m_b;
};
class ClassC : public ClassB
{ public: int m_c;
void SetB(){m_c=2;}
};
void f1(int,float){}
void f2(ClassC*,long){}
void main()
{ double d=1;
const type_info& t1=typeid(f1); const type_info& t2=typeid(f2);
printf("%s,\t%s\n", t1.name(),t1.raw_name());
printf("%s,\t%s\n", t2.name(),t2.raw_name());
ClassC c; ClassB& rb=c;
const type_info& tc=typeid(ClassC*); // typeid(e)是const对象,别名也是const属性
const type_info& tb=typeid(rb); //声明typeid(rb)的别名tb简化代码书写量
if(t1.before(t2))
printf("1--t1.before(t2)\t");
if(strcmp(t1.raw_name(),t2.raw_name())<0)
printf("2--t1.before(t2)\n");
if(tb.before(tc))
printf("3--%s,\t%s\t", tb.name(),tc.name());
if(strcmp(tb.raw_name(),tc.raw_name())<0)
printf("4--%s,\t%s\n", tb.name(),tc.name());
void* vp=&d;
printf("%s,\t%s\n", typeid(vp).name(),typeid(*(double*)vp).name());
}///////////////输出结果://///////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -