?? ex19.cpp
字號:
// 第19章 多態(tài)和虛函數
// [例19.1] 關鍵字virtual的開關作用和隱約調用
#include <stdio.h>
class ClassX //基類的成員函數F()是公共的,由關鍵字virtual修飾,F(xiàn)()是虛函數
{ public: virtual void F();//去掉前置關鍵字virtual,則F()不是虛函數
private: long m_nx;
};
void ClassX::F() {printf("ClassX=%d,",sizeof(ClassX));}
class ClassY:public ClassX
{ private: long m_ny;
void F(); //派生類的覆蓋版本是私有的
};
void ClassY::F(){ printf("ClassY=%d,",sizeof(ClassY)); }
void Showv(ClassX objx){ objx.F(); } //數值形參調用虛函數,靜態(tài)聯(lián)編
void Show(ClassX* pBase){ pBase->F();} //指針形參隱約調用虛函數,動態(tài)綁定
void Show(ClassX& r){ r.ClassX::F(); } //引用形參顯式調用虛函數,靜態(tài)聯(lián)編
void main() //若將{r.ClassX::F(); }改為{r.F(); }則虛函數對應動態(tài)綁定
{ ClassX* pobjx=new ClassX();
ClassY objy; int k=1;
scanf("%d",&k);
if(k==1) { Show(pobjx); Show(&objy);} // k=1調用指針形參的Show版本
else { Show(*pobjx); Show(objy); } // k不等于1調用引用形參Show版本
Showv(objy); // Showv調用中實參是派生類對象objy,形參是基類對象objx
}
// [例19.2]靜態(tài)聯(lián)編調用非虛成員函數,派生類的覆蓋版本是公共的
#include <stdio.h> //這里的類與前面的題相似,但取消了關鍵字virtual
class ClassX { long m_nx; public: void F(); };
class ClassY:public ClassX { long m_ny; public: void F(); };
void ClassX::F() { printf("ClassX=%d,",sizeof(ClassX)); }
void ClassY::F() { printf("ClassY=%d,",sizeof(ClassY)); }
enum {classx,classy};
void Show(ClassX* pBase,int morph)
{ switch(morph)
{ case classx: pBase->F();break;
case classy: ((ClassY*)pBase)->F();break;//此處調用要求ClassY::F()是公共的
} //(ClassY*)pBase 將基對象指針pBase向下轉換到派生類指針ClassY*
} //這種轉換扮演指針復原的作用,pBase獲得的動態(tài)值應指向派生類對象
void main() // void Show(ClassX& rBase,int morph)
{ Show(new ClassX(),classx); //{ switch(morph){
Show(new ClassY,classy); // case classx: rBase.F();break;
} // case classy:((ClassY&)rBase).ClassY::F();break;}
// 輸出:ClassX=4, ClassY=8, //} /*與指針形參版本相當的引用形參版本*/
///[例19.3]對象引用的隱含類型轉換作用
# include<stdio.h>
class CIo { public: char obuffer[48]; };
class CStream : public CIo { public: CStream& operator<<(double); };
class CWithassign : public CStream { public: };
CStream& operator<<(CStream& r,int n) //全局運算符函數
{ static const char* fmt = "operator<<( CStream&, %d);";
sprintf(r.obuffer,fmt,n); printf("%s",r.obuffer);
return r;
}
CStream& CStream::operator<<(double d) //成員運算符函數
{ static const char* fmt = "CStream::operator<<(double d=%f);\n";
sprintf(obuffer,fmt,d); printf("\n%s",obuffer);
return *this;
}
void main()
{ CWithassign wout; operator<<(wout,1);
wout<<2<<3; wout<<4.0;
CIo cio; operator<<((CStream&) cio,5);
(CStream&) cio<<6<<7;
}//程序運行輸出結果:
// [例19.4] 虛析構函數在動態(tài)綁定中的重要性
#include <stdio.h>
class ClassX
{ public: virtual ~ClassX(){printf("~ClassX();");} //公共的析構函數
protected: ClassX() { printf("ClassX();"); } //保護的構造函數由派生類調用
};
class ClassY:public ClassX
{ public: ClassY(int n=1) //公共的構造函數由new ClassY()調用
{ m_n=n; m_p=new long [m_n]; printf("ClassY();"); }
private: ~ClassY() { delete [] m_p; printf("~ClassY();"); }
long m_n; long* m_p;
};
void main()
{ ClassX* pobjx= new ClassY(); //在調用點構造函數ClassY()應是可訪問的
delete pobjx; //在調用點析構函數~ClassX()應是可訪問的
}
//[例19.5]函數調用運算符成員函數operator()作為虛函數
#include <stdio.h>
struct SB //公共屬性的虛函數int operator()(int i)
{ virtual int operator()(int i)=0{return a[i];} //抽象類的純虛函數可以提供代碼
static int a[]; //聲明靜態(tài)的數組成員
}; //聲明兩個派生類并內置定義int operator()(int i)成員函數的覆蓋版本
struct SC:public SB{ int operator()(int i) {return a[i+1];} };//派生類覆蓋版本是虛函數
struct SD:public SC{ int operator()(int i) {return a[i+2];} };
int f(SB& r){ return r(1);} //全局函數以對象引用方式調用int operator()(int)虛函數
void main() // r(1)相當于r.operator ()(1),動態(tài)綁定在虛函數調用點發(fā)生作用
{ SD d; //定義派生類對象d,c
SC c; //f(d),f(c)函數調用導致派生類對象向上隱含地轉換為基對象引用
printf("%d,%d,%d\n",f(d),f(c),d.SB::operator ()(1)); //輸出:3,2,1
} // d.SB::operator ()(1)顯式地調用抽象類的純虛函數
int SB::a[]={0,1,2,3,4,5,6,7,8,9,10}; //全局范圍定義靜態(tài)的數組成員
// [例19.6] 指向成員函數的指針和虛函數
#include <stdio.h>
class B; //類B的前置說明,滿足下面定義語句的需要
void (B::*pfm)(); //定義全局的void (B::*)()型的指向成員函數的指針pfm
class B
{ virtual void f()=0; //私有屬性的純虛函數f
public:static void set(){pfm=&B::f;}// 成員函數指針pfm指向私有的虛成員函數
};
class D:public B{ void f(){printf("D::f();\n");} };
void main()
{ D objd; //定義派生類對象objd
B*pobjb=&objd; //派生類對象地址向上映射到基對象指針
B::set(); //調用靜態(tài)成員函數,得到pfm=&B::f;
(pobjb->*pfm)(); //等價于pObjb->f();
} //輸出結果:D::f();
288
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -