⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ex19.cpp

📁 C/C++程序设计教程
💻 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 + -