?? 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 + -