📄 ex15.cpp
字号:
//第15章 特殊的成员函数
//[例15.1]定义对象数组CA a[2];导致两次调用缺省构造函数。程序输出:2,3,13
#include <stdio.h> //定义对象b(10)调用构造函数CA(int m),m=10
static int cx=1; const int constn=0;//cx是静态全局变量,constn是整型立即数
class CA { public: CA(int m=1){x= constn +m+cx++; } long x; } ;
void main() { CA a[2],b(10); printf("%d,%d,%d",a[0].x,(a+1)->x,b.x); }
//[例15.2]构造函数的调用
#include <stdio.h>
static int n=0; //静态的全局变量n纪录构造函数调用次数
class CType
{ public: CType(){m_n=n++; }
int m_n;
};
CType d; //定义全局对象d,d调用构造函数一次,使得n变化为1
void fs(){static CType s;printf("s.%d\t",s.m_n);} //静态对象最多仅调用一次构造函数
void fa(){CType a ;printf("a.%d\t",a.m_n);} //非静态的局部对象a每次都调用构造函数
void main() { fs(); fs(); fa(); fa(); }
// 输出:s.1 s.1 a.2 a.3
////////////[例15.3] 函数对象名语法
#include <stdio.h>
#include<string.h>
class CType
{ int m_n;
public: CType(int n=1){m_n=n; } //单参构造函数内置定义
void operator()(const CType* s); //函数名为operator()的成员函数
void Show(char*s) {printf("%s,n=%d\t",s,m_n);}
};
void CType::operator()(const CType* s) // const CType* 入口形参为指向对象的指针
{ // operator()是函数调用()运算符函数
memcpy(this,s,sizeof(CType)); //此函数执行对象数据的拷贝功能
}
CType d(); //全局函数原型说明,这是一个未被调用的函数。
void main()
{ CType d(1); //定义局部对象d,d调用构造函数CType(int)
d.Show("d(1)"); //对象调用成员函数Show(char*s)
CType *p=new CType(2); //先调用new函数,new调用构造函数CType(int)
d(p); d.Show("d(p)"); // d(p)函数对象名语法调用成员函数operator()
d=CType(3); d.Show("CType(3)");// d=CType(3)为显式调用构造函数CType(int)
CType(4).Show("CType(4)"); //无名对象CType(4)调用成员函数Show(char*)
} //输出:d(1),n=1 d(p),n=2 CType(3),n=3 CType(4),n=4
//////////[例15.4] 构造函数的显式调用构成初始化列表
#include <stdio.h>
static int cnum=1; static int cx=-1,cy=-1;
struct CA
{ CA() { x=cx--; y=cy--; printf("%d.CA(%d,%d);\n",cnum++,x,y);}
CA(int m,int n){x=m;y=n; printf("%d.CA(+%d,+%d);\n",cnum++,x,y);}
long v(){ return x; }
private: long x; long y;
} ; /*程序运行输出结果:*/
void main() /*1. CA(-1,-1);*/
{ CA a[2]; /*2. CA(-2,-2);*/
CA d[3]={CA(1,1),CA(2,2)}; /*3. CA(+1,+1);*/
d[2]=CA(3,3); /*4. CA(+2,+2);*/
if(d[1].v()==(d+1)->v()) /*5. CA(-3,-3); */
printf("d[1].v()=(d+1)->v()"); /*6. CA(+3,+3);*/
} /*d[1].v()=(d+1)->v()*/
/////////////[例15.5]对象定义与析构函数
#include <stdio.h>
static int numc=0; //静态全局变量纪录析构函数的反序调用次数
class CType
{ public: CType(int=3 ); //缺省值为3的构造函数
~CType(); //析构函数无参也无返回类型
private: long * m_p; //一个指针成员用于定位动态数组
int m_n; //描述动态数组的动态维数
};
CType::CType(int n) //单个参数入口的构造函数
{ m_n=n;
printf("%d,CType();++%d\n",m_n,++numc);
m_p=new long[m_n]; //构造函数中分配动态数组的内存空间
}
CType::~CType()
{ printf("%d,~CType();%d--;",m_n,numc--);
delete [] m_p; //清除动态long型数组的内存空间
}
CType g(1); //定义全局对象g,调用CType(1)
CType *q=new CType(9); //定义堆中对象*q,这个*q对象没有被delete q清除
void main() //因此相应的析构函数未被调用
{ printf("Enter into main(){\n"); //进入主函数的势力范围
CType d(2); //定义局部对象d,调用CType(2)
CType *pk=new CType[2]; //定义两个堆中对象,2次调用CType(3)
delete [] pk; //清除此数组的两个对象
printf("\nGo outof main() }\n"); //退出主函数的作用范围
} //程序运行输出结果:
//////////////[例15.6] 赋值运算符函数与拷贝构造函数
#include <stdio.h>
#include<string.h>
class B
{private:int m_n;
public: B(int v=1){Set(v); } //单参数缺省构造函数
B(const B& r); //拷贝构造函数
B& operator=(const B& r); //等号运算符函数
void Set(int n){m_n=n; } //设置成员变量的函数
void Show() {printf("n=%d;",m_n);} //显示成员状况的函数
};
B::B(const B& r) //拷贝构造函数copy constructor
{ printf("call B::B(const B& r);"); //屏显语句通常是多余的
memcpy(this,&r,sizeof(B)); //调用内存拷贝函数,this指向调用成员函数的对象地址
} //调用成员函数的对象即当前对象
B& B::operator=(const B& r) //assignment函数
{ printf("call B& B::operator=(const B& r);");
if(this==&r) return *this; //如果入口r的地址等于当前对象的地址,返回当前对象
memcpy(this,&r,sizeof(B)); //简单的内存拷贝
return *this; // return *this返回调用该成员函数的对象
} //this此时是B*const型的指针,间接对象*this即当前对象是B型左值
void main()
{ B d; //调用有缺省值的构造函数B(int v=1)
d.Show(); //显示d(1)初始化后的结果
B a=d; //调用拷贝构造函数B(const B& r)
a.Show(); //显示a(d)初始化后的结果
a.Set(100); //将a.m_n设置为100
d=a; //调用函数B& operator=(const B& r);
d.Show();
} //输出:n=1;call B::B(const B& r);n=1; call B& B::operator=(const B& r);n=100
//////////// [例15.7]拷贝构造函数的隐含作用
class A
{ public: A(int n) { m_n=n; }
~A() { }//这相当于编译器提交的缺省析构函数
private: A(const A& r) { m_n=r.m_n; }
int m_n;
};
void f(A a) { }
A g(int n) { return A(n); } //error : cannot access private member
void main()
{ A d(2); A b=10;
A a=d; //error : cannot access private member
f(b); // error :cannot access private member
}
///////////[例15.8] CRect类中的重载函数SetRect
#include<string.h>
#include<stdio.h>
class CRect
{ public: long left; long top;
long right; long bottom;
CRect(int l=1, int t=2, int r=3, int b=4);
void SetRect(int x1, int y1, int x2, int y2);
void SetRect(const CRect& r) ;
void Show();
};
void CRect::Show() //成员函数显示自身的数据
{
printf("left=%d,top=%d,right=%d,bottom=%d;", left,top,right,bottom);
}
void CRect::SetRect(const CRect& r) //设置矩形函数
{
left =r.left; top = r.top; right = r.right; bottom = r.bottom;
}
CRect::CRect(int l, int t, int r, int b) //带参构造函数缺省值全部设置
{ SetRect(l,t,r,b); } //构造函数调用自身的成员函数
void CRect::SetRect(int l, int t, int right, int bottom)
{ //设置矩形坐标值的成员函数
left = l; top = t; this->right = right; this->bottom = bottom;
}
void main()
{ CRect r,s; //定义对象导致调用构造函数CRect(1, 2, 3, 4)
r.Show(); //r对象显示数据
r.SetRect(5,6,7,8); //调用成员函数SetRect(int , int , int, int)
s.SetRect(r); //调用成员函数SetRect(const CRect& r)
s.Show(); //s对象显示数据
} //输出:left=1,top=2,right=3,bottom=4;left=5,top=6,right=7,bottom=8
///[例15.9]缺省参量的构造函数和成员函数
#include<stdio.h>
class CType
{ long m; int n; short s;
public: void Set(int n,long m=10,short s=5);
CType(int n=1,long m=10,short s=5);// 全部设置缺省值的构造函数
void Show();
CType(){} //无参构造函数
}; //warning : 'CType' : multiple default constructors specified
void CType::Set(int n,long m,short s)
{ this->n=n;this->m=m;this->s=s; }
CType::CType(int n,long m,short s) { Set(n,m, s) ;}
void CType::Show() { printf("%d,%d,%d \n",n,m,s); }
void main()
{ CType* pthis=new CType(1); //pthis=new CType()导致歧义
pthis->Set(7,10,5); pthis->Show();//输出:7,10,5
pthis->Set(7,10); pthis->Show();//输出:7,10,5
CType a(7,10,5); a.Show(); //输出:7,10,5
CType c(7,10); c.Show(); //输出:7,10,5
}
/////////// [例15.10]编译器默默奉献的成员函数清单
#include <stdio.h>
#include<string.h>
class CType
{ long m_tData;
public: CType(){} //1无参空构造函数
~CType(){} //2无参空析构函数
CType(const CType& r) ; //3拷贝构造函数
CType& operator=(const CType& r); //4等号运算符函数
inline CType* operator&(); //5取可变对象地址运算符函数
inline const CType* operator&()const; //6取只读对象地址运算符函数
}; //取只读对象地址运算符函数返回const CType*型的只读地址值
int and=0;//设置and变量纪录取地址运算符函数调用情况,and原本是多余的
CType::CType(const CType& r) { memcpy(this,&r,sizeof(CType)); }
CType& CType::operator=(const CType& r)
{ if(this==&r) return *this; //函数名为operator=的双目运算符函数
memcpy(this,&r,sizeof(CType));
return *this;
} //函数名为operator&的单目运算符函数
inline CType* CType::operator&() {and=1; return this;}
inline const CType* CType::operator&() const {and=2; return this;}//只读版本
void main() //and=1; and=2;原本是多余的
{ CType v; //定义左值对象v
CType* pv=&v; //取左值对象地址,调用operator&()
printf("%d\t", and);
const CType c; //定义只读对象c,只读指针pc
const CType* pc=&c; //取只读对象地址,调用operator&() const
printf("%d\t", and); and=0;
pc=v.operator&() ; //显式调用名为operator&的取地址运算符函数
printf("%d\t", and);
} //输出:1 2 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -