?? 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是靜態(tài)全局變量,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; //靜態(tài)的全局變量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);} //靜態(tài)對象最多僅調用一次構造函數
void fa(){CType a ;printf("a.%d\t",a.m_n);} //非靜態(tài)的局部對象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)); //此函數執(zhí)行對象數據的拷貝功能
}
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; //靜態(tài)全局變量紀錄析構函數的反序調用次數
class CType
{ public: CType(int=3 ); //缺省值為3的構造函數
~CType(); //析構函數無參也無返回類型
private: long * m_p; //一個指針成員用于定位動態(tài)數組
int m_n; //描述動態(tài)數組的動態(tài)維數
};
CType::CType(int n) //單個參數入口的構造函數
{ m_n=n;
printf("%d,CType();++%d\n",m_n,++numc);
m_p=new long[m_n]; //構造函數中分配動態(tài)數組的內存空間
}
CType::~CType()
{ printf("%d,~CType();%d--;",m_n,numc--);
delete [] m_p; //清除動態(tài)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 + -