📄 ex19.cpp
字号:
// 第19章 多态和虚函数
// [例19.1] 关键字virtual的开关作用和隐约调用
#include <stdio.h>
class ClassX //基类的成员函数F()是公共的,由关键字virtual修饰,F()是虚函数
{ 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(); } //数值形参调用虚函数,静态联编
void Show(ClassX* pBase){ pBase->F();} //指针形参隐约调用虚函数,动态绑定
void Show(ClassX& r){ r.ClassX::F(); } //引用形参显式调用虚函数,静态联编
void main() //若将{r.ClassX::F(); }改为{r.F(); }则虚函数对应动态绑定
{ 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]静态联编调用非虚成员函数,派生类的覆盖版本是公共的
#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获得的动态值应指向派生类对象
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] 虚析构函数在动态绑定中的重要性
#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[]; //声明静态的数组成员
}; //声明两个派生类并内置定义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),动态绑定在虚函数调用点发生作用
{ 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}; //全局范围定义静态的数组成员
// [例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(); //调用静态成员函数,得到pfm=&B::f;
(pobjb->*pfm)(); //等价于pObjb->f();
} //输出结果:D::f();
288
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -