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

📄 ex16.cpp

📁 这里有大量的习题解答
💻 CPP
字号:

			//第16章  数据的共享和流通

    //[例16.1]深拷贝方式
	#include <stdio.h>  
    #include<string.h>    
	class CDeep
    {	public: int    n;                       //描述动态数组的动态维数	
              int   *p;                       //指针成员用于定位动态数组	
 			CDeep(int) ; 		
			~CDeep();
            CDeep(const CDeep& r) ;                 //提交定制的拷贝构造函数 
			CDeep& operator=(const CDeep& r); 		  //提交定制的等号运算符函数	
      	}; 	
	CDeep::~CDeep()	
    {  static int s_num=1;	
	   printf("%d.~CDeep()\t",s_num++); 
	   delete [] p;  
    }
	CDeep::CDeep(int k)                       //单参数入口的构造函数
	{	n=k;		
        p=new int[n];                          //定义动态数组int p[n]
	}	
	CDeep& CDeep::operator=(const CDeep& r)     //定义等号赋值运算符函数     
	{	if(n!=r.n)                              //两个深部数组长度不一致时
		{   delete [] p;                         //释放原来的数组空间
			n=r.n;		                     //设置两个数组长度相等
			p=new int[n];                      //建立与源数组等长的独立数组
		}                                    //确保目标数组拥有独立的资源
		memcpy(p,r.p,n*sizeof(int));	             //拷贝动态资源的物理数据 
		return *this;                           //返回物理数据一致的当前对象
	}	
	CDeep::CDeep(const CDeep& r)              //拷贝构造函数
	{   	n=r.n;		                         //当前数组维数等于源数组维数
		p=new int[n];                          //建立独立的内存资源
 	    memcpy(p,r.p,n*sizeof(int));		         //物理数据全盘拷贝
	}
	void main()
	{	CDeep a(2),d(3);	                      //定义外层局部对象a,d
		 a.p[0]=1;  d.p[0]=666;                    //对象a,d深部数组元素的赋值
			{   CDeep b(d);                     //调用拷贝构造函数
                a.p[0]=88;
				b=a;                           //调用等号赋值运算符函数
                printf("%d;",b.p[0]);              //显示内层局部对象的深部数组元素  
			}                                  //b调用析构函数清理深部资源
        printf("%d;",d.p[0]);                      //显示d深部数组元素a.p[0的值
		printf("b fade out away;\t");                //记录b淡出的标记
		printf("%d;",a.p[0]);                      //显示a深部数组元素a.p[0的值
	}	
//[例16.2] const对象与只读成员函数。
	#include<stdio.h>
	struct CPoint	{     long  x;    long  y;	     } ;
	class CRect
	{	public:	    CRect(int l, int t, int r, int b);
		CPoint& TopLeft();                 	// top-left point的引用返回	
		const CPoint& TopLeft() const;	        //const reference to the top-left point
		private:		long    left;		long    top;
		            long    right;		long    bottom;
	};
	inline CRect::CRect(int l, int t, int r, int b)
		{    left = l; top = t; 	  right = r; bottom = b;		}
	inline CPoint& CRect::TopLeft()			{ return *((CPoint*)this); }	
	inline const CPoint& CRect::TopLeft() const
	{                    // 返回引用的只读函数需双边const限制以维持内外一致
		 return *((CPoint*)this);     //(CPoint*)this指针类型转换
	 }      //*this是CRect型的左值, *(( CPoint *) this)是CPoint型的左值
	void main()
	{	CRect r(10,20,30,40);	           //普通对象r调用构造函数
        CPoint& rtl =r.TopLeft();           //声明引用rtl简化表达式的书写
	    const CRect d(rtl.x+5,rtl.y+5,35,45);  //只读对象d调用构造函数
        CPoint  dtl(d.TopLeft());          //定义对象dtl,调用拷贝构造函数
		printf("left=%d,top=%d\t",rtl.x,rtl.y);
		printf("left=%d,top=%d\n",dtl.x,dtl.y);
	}	//输出:left=10,top=20  left=15,top=25
//[例16.3] volatile关键字的用法
	#include <stdio.h>  
    class B
	{     volatile int	m_n;	 
	public:	B(int v=1){   m_n=v;  }	
		void Set(int n) volatile        {   m_n=n; }
		void Show()    const      {  printf("Show()const; n=%d\n",m_n);}   
		void Show()    volatile    {  printf("Show() volatile; n=%d\n",m_n);}
		void Show()              {  printf("Show() ;n=%d\n",m_n); }
	};	
    void main()                            /*程序输出结果:   */
	{     const	 B c;      c.Show();        /*Show() const; n=1  */
	     volatile	 B v(2);    v.Show();        /*Show() volatile; n=2*/
		 v.Set(3);	          v.Show();       /*Show() volatile; n=3  */
	     B x(4);  		  x.Show();        /*Show() ; n=4      */
	}
//[例16.4] mutable关键字注册绝对可变的成员
	#include <stdio.h>  
	class CType 	{	 public:   mutable	 long  v;   long  n; 	    };   
	void main()
	{	const CType cobj={1,2};printf("cobj={%d,%d};\t",cobj.v,cobj.n);
	    cobj.v=8;             printf("cobj={%d,%d};\n",cobj.v,cobj.n);
		//cobj.n=2;  error : l-value specifies const object
	}   //输出结果:cobj={1,2};    cobj={8,2};
//[例16.5]友元函数将类回归到经典的公共访问性质的结构
    #include <stdio.h>
	struct S{int e;};                    //结构成员e是公共访问性质
    class B;                            
	class A
	{	private: int a;
		public:  void add(B& );         //成员函数中B& 型的形参要求前置说明
        friend   void swap(A*,B& );      //声明全局函数swap是A类的友元函数 
		int&  Ea(){return a;}            //公共成员函数Ea等价地导出私有成员a
 	};	
    class B                           //访问控制属性不影响friend	
	{	friend void swap(A *p,B& r);       //声明全局函数swap为 B类的友元函数   
	    private: 	int b;
	    friend void A::add(B& r);        //A类的成员函数add是B类的友元函数
		public: int& Eb(){return b;}     //公共成员函数Eb等价地导出私有成员b
	};	
    void  PublicB(S *p,B& r)   //B&形参 r只能访问公共成员Eb
	{   r.Eb()=1;             //不能访问私有成员b
    //	p->e=r.b;             //error  'b' : cannot access private member
	}
	void swap(A *p,B& r)       // 全局函数swap是类A类B这两个类的友元函数
	{	int t=p->a;             //A*型形参p访问A类的任意成员
		p->a=r.b; r.b=t;         // B&型形参r访问B类的任意成员
	}
    void A::add(B& r)  
	{                        // add是类B的友元函数
	   a+=r.b;                //因此B&型形参r可以访问其私有成员
	}
	void main()	{ A x;   x.Ea()=1;	    B y;     y.Eb()=2;
	              x.add(y);           swap(&x,y);
	              printf("%d,%d\n",x.Ea(),y.Eb());        }     //输出2,3	
//	[例16.6]友元类B将当前类A视为一个公共访问控制属性的结构
	#include <stdio.h>     
    class B;
	class A                                  //声明类B为类A的友元类其含义就是
	{	friend   class B;                      //允许类B将类A当作一个公共的结构
		 private: int  m_a;		
			A(int k=0){m_a=k;}                //私有的全缺省值的构造函数       
		public:	friend	void g_f();		     //声明全局友元函数g_f
		void 	Show(){printf("m_a=%d\t",m_a);}
	};
    class B
	{	int m_b;	   
        A a;                             //在类B中声明一个类A的嵌入对象a
	   public:B(int k=1){ m_b=k; a.m_a=1+k; } //嵌入对象a访问私有成员m_a
			A& Add(A* );                 //B类的成员函数是类A的友元函数
	};	
    A& B::Add(A* p)                      // A*型指针入口,A&型引用返回
    {	p->m_a+= a.m_a+m_b;              // p访问类A的私有成员m_a
		return *p;
	}
	A* pa;                               //定义全局指针以导出静态局部对象d
	void g_f()                            // g_f()全局函数是A类的友元函数
	{   A a;                             //定义局部对象调用私有的构造函数
		a.m_a=1;                         //圆点运算符访问对象的私有成员
		a.Show();
		static	A d(100);                //定义静态的局部对象d 
		 pa=&d;                          //全局指针指向静态对象d
	}
    void main()
	{ 	g_f();                            //调用全局函数
		B b;	                             //定义对象b
		b.Add(pa).Show();                  //b.Add(pa)的结果就是静态局部对象d
	}		//输出:m_a=1,m_a=103
///[例16.7]静态成员变量的声明、定义和使用
	#include <stdio.h>      	
    static  long* pa;                  //定义一个封装文件内的静态的全局指针pa
	class CType
	{	public:                            //公有访问属性:
		static   int   data;                 //静态成员声明语句遵守不赋初始值的规则   
		 CType(int n=1){ m_n=n;data++;  } 	//静态成员data记录诞生对象的个数
        static	void f()       //静态成员函数内置定义	  	
        {         // 静态成员sa的地址是一个常规的long*型的地址
          pa=sa;  //静态的全局指针pa初始化为保护属性的sa
        }        //对pa[k]的操作就是对于CType::sa[k]的操作,但pa[k]可以在外部访问
		protected: static	 long sa[]; //静态成员声明语句不涉及其内存分配
        private:    int m_n;
	};  
int		   CType::data;             //相当于 int   CType::data=0;
    long   CType::sa[]={20,30,40};        //此时补充数组的完备信息
	void main()
	{ 	CType::data=0; 
	    printf("%d,static data=%d\t",sizeof(CType),CType::data);
        CType::f();                       //调用静态成员函数pa= CType::sa;
        printf("pa[0]=%d,pa[1]=%d,pa[2]=%d\n",pa[0],pa[1],pa[2]);
	}      //输出:4,static data=0       pa[0]=20,pa[1]=30,pa[2]=40
////	[例16.8] 静态成员对象实质上是全局对象, 静态成员函数实质上是全局函数
	# include<stdio.h>
	class A
    {   private:                           //将全局对象static A a平移到类域中
		static A a;                          //静态私有成员是独立于当前类的对象
		int m_n;                            //当前类实例的成员变量
		A(int n)                           //私有的构造函数禁止外部定义对象
        { 	 m_n=n;	   printf("call A::A();\t");        }
	public:
		static A& GetStatic();                //返回对象引用的静态成员函数
		int GetNum(){return this->m_n;}       //公共的成员函数取私有数据状态
	};
	inline	A& A::GetStatic()//定义inline型的静态成员函数
    	{return a;}           //内联映射使得函数调用A::GetStatic()等价于a
	A  A::a(10);             //文件范围内定义名称为A::a的静态私有成员对象
	void main()
   {		printf("Here is in main scope\t");
		printf("m_n=%d\t",A::GetStatic().GetNum());
        A& (*pf)()=A::GetStatic;        //常规函数指针pf获得静态成员函数的地址
		printf("m_n=%d\n",pf().GetNum());//pf()的结果就是对象A::a
	}	//输出:call A::A();    Here is in main scope   m_n=10    m_n=10
///	[例16.9]指向数据成员的指针,静态成员函数的地址属性同等于全局函数的地址属性
	#include <stdio.h>      	
	class CType                          
	{   public:static	 void Setpm(int  CType::* & ,int k);//静态成员函数声明
		 void Set(int  CType::*& pm,int k){Setpm(pm,k);this->*pm+=k;}		 
	   CType(int x=10,int y=20)		  {  m_t1=x;   m_t2=y;    } 
		  void Show()  {	  printf("m_t1=%d,m_t2=%d\t",m_t1,m_t2);}        
	    public:  int  m_t1;
		private: int  m_t2;			   	
		};
    void CType::Setpm( int  CType::*&  pm,  int k)   //引用形参pm便于数据的传递
   	{                      //开关变量k用于分流指向成员的指针赋值
  		if(k==1) pm=&CType::m_t1;           //入口局部指针pm关联公共变量
		else     pm=&CType::m_t2;          //指向成员的指针pm关联私有变量 
	}                            //静态成员函数CType::Setpm实质上是全局函数
    void (*Setpm)( int CType::*& ,int)= CType::Setpm;//定义一个常规函数指针Setpm 
	void main()                         // Setpm 指向静态成员函数CType::Setpm
	{   int  CType::* pm;              //定义指向成员数据的局部指针pm
        CType::Setpm(pm,1); //调用静态成员函数CType::Setpm,得pm=&CType::m_t1
        CType a;                       //定义局部对象a(10,20)
	    a.Show();                       //显示默认的设置值	   
	    a.*pm+=10;                      //成员指针访问公共的成员变量	 m_t1
	    Setpm(pm,2); //常规函数指针间接调用静态成员函数,得到pm=&CType::m_t2; 
	    a.*pm+=20;                     //成员指针访问私有的成员变量m_t2
        a.Set(pm,1);                    // 得到pm=&CType::m_t1;a.*pm+=1;
	    a.Show();                 	   //显示运算后的结果
	}		//  输出:m_t1=10,m_t2=20    m_t1=21,m_t2=40
 //   [例16.10]指向成员函数的指针                                                                                                                                                                                                                                                 
	#include <stdio.h>      
	class CType;	typedef int  (CType::*PFM)(int);
	class CType                          
	{  public: static void Setpfm(PFM & pfm,int);   //静态成员函数设置成员指针
		CType(int x=0){pfm(x);}
		void Show(){ printf("m_x=%d\t",m_x); }
        int   pfm(int x){m_x=x;  return 2;}  //公共属性的成员函数pfm
	 private: int   Add(int x){m_x+=x;  return 1;}  //私有成员函数
	       int   m_x;	  		
	};  
    void CType::Setpfm(PFM & pfm,int num)          //成员函数指针引用形参完成
	{	switch(num)                             //取成员函数地址的工作
		{case 1:   pfm=&CType::Add;break;              //获取私有成员函数的地址
		default:   pfm=&CType::pfm;break;              //获取公共成员函数的地址
		}	
	}
    int  (CType::*gpfm)(int)=&CType::pfm;  //全局性的指向成员函数的指针gpfm
                                                // gpfm指向公共的成员函数
   	void main()
	{	CType* pthis=new CType();
		(pthis->*gpfm)(10); pthis->Show();
		PFM pfm;                      //定义一个PFM型的局部变量pfm
		CType::Setpfm(pfm,1);            // 1.pfm=&CType:: Add;
		(pthis->*pfm)(20);  pthis->Show();  //(pthis->*pfm)(20) 等价于pthis-> Add (20)
		CType::Setpfm(pfm,2);            // 2.pfm=&CType:: pfm;
		(pthis->*pfm)(3);   pthis->Show();   // (pthis->*pfm)(3)等价于pthis->pfm(3)
		   pthis->pfm(4);  pthis->Show();
	}			//输出:m_x=10   m_x=30   m_x=3, m_x=4




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -