📄 ex16.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 + -