# 構造函數
在宣告一個對象後,緊接著要給對象初始化,對象初始化實質上就是對所有數據成員賦值。
如果對象中某個數據成員未賦值,則該數據成員的值不確定,那麼該對象的值不完整。
構造函數 Constructor
用於創建一個對象,提供了初始化該對象的一種簡便手段。
注意:
- 構造函數的函數名必須與類名相同
- 構造函數沒有返回值
- 其功能是將對象中的所有數據成員進行初始化,一般由一系列賦值語句構成
- 由系統在宣告對象時自動調用
# 有無構造函數的區別
在前面章節中的程序宣告變數
| int a=0; |
| int a(0); |
| struct Date today={2013,3,19}; |
| struct Date today(2013,3,19); |
以上為變數宣告的同時賦初值,即都允許初始化。
| CLOCK alarm={10,53,11}; |
| CLOCK alarm(10,53,11); |
| Date birthday(1998,12,12); |
| Date birthday={1998,12,12}; |
# 重載構造函數
- 一個類中允許定義多個構造函數
- 在宣告對象時自動選擇執行某個構造函數
數據成員初始化的四種方法:
- 在構造函數的函數體中進行初始化
| Date(Date &d) |
| { |
| year=d.year; |
| month=d.month; |
| day=d.day; |
| } |
- 在構造函數的頭部初始化
| <類名>::<構造函數名>(<參數表>):<變數1>(<初值1>),…<變數n>(<初值n>){…} |
| |
| Date::Date():year(1900),month(1),day(1) |
| { |
| |
| } |
- 混合初始化:前兩種方式結合
| Date::Date(int y,int m,int d):year(y),month(m) |
| { |
| day=d; |
| } |
- 使用默認參數初始化
| Date(char yy[], int mm = 1, int dd = 1) |
| { |
| year = atoi(yy); |
| month = mm; |
| day = dd; |
| } |
# 例子:日期類中 4 個重載構造函數
| #include<iostream> |
| #include<string.h> |
| #include<stdlib.h> |
| using namespace std; |
| class Date |
| { |
| int year,month,day; |
| |
| public: |
| |
| Date():year(1900),month(1),day(1) { } |
| |
| Date(int yy,int mm = 1,int dd = 1); |
| |
| Date(Date &d):year(d.year),month(d.month),day(d.day){}; |
| |
| Date(char *ps); |
| void print_ymd(); |
| }; |
| |
| |
| Date::Date(int yy,int mm,int dd):year(1900),month(1),day(1) |
| { |
| if (yy>=1900&&yy<=9999) |
| { |
| year = yy; |
| } |
| else |
| { |
| return; |
| } |
| if (mm>=1&&mm<=12) |
| { |
| month = mm; |
| } |
| else |
| { |
| year=1900; |
| return; |
| } |
| if (dd>=1&&dd<=31) |
| { |
| day = dd; |
| } |
| else |
| { |
| year=1900; |
| month=1; |
| return; |
| } |
| }; |
| |
| |
| Date::Date(char *ps):year(1900),month(1),day(1) |
| { |
| char py[5],pm[3],pd[3]; |
| strncpy(py,ps,4); |
| ps=ps+5; |
| strncpy(pm,ps,2); |
| ps=ps+3; |
| strncpy(pd,ps,2); |
| int yy=atoi(py),mm=atoi(pm),dd=atoi(pd); |
| if (yy>=1900&&yy<=9999) |
| { |
| year = yy; |
| } |
| else |
| { |
| return; |
| } |
| if (mm>=1&&mm<=12) |
| { |
| month = mm; |
| } |
| else |
| { |
| year=1900; |
| return; |
| } |
| if (dd>=1&&dd<=31) |
| { |
| day = dd; |
| } |
| else |
| { |
| year=1900; |
| month=1; |
| return; |
| } |
| } |
# 析構函數
構造函數 Constructor
:在對象創建時執行,提供了初始化對象的一種簡便手段。
析構函數 Destructor
:在對像被撤銷時 (前) 執行,用於完成對像被撤銷前的一些清理工作。
具體地說,析構函數往往用於釋放 “資源”,如在構造函數中動態申請的內存空間。
也可以被用來執行 “用戶希望在最後一次使用對象之後所執行的任何操作”,例如輸出有關信息等。
# 對象的存儲空間
每個對象中的數據成員分配了存儲空間。
所有對象中的函數成員共用一個存儲空間,在代碼區存放。
# 定義方式
- 注意:
- 函數名是類名前面加
~
符號 - 析構函數不得返回任何值
- 析構函數不得帶有任何參數
- 其主要功能是在撤銷對象之前進行一些善後處理工作
- 由系統自動調用
- 例子:日期類中增加析構函數
| #include<iostream> |
| using namespace std; |
| class Date |
| { |
| int year,month,day; |
| public: |
| |
| Date():year(1900),month(1),day(1) { } |
| |
| Date(int yy,int mm = 1,int dd = 1); |
| |
| Date(Date &d):year(d.year),month(d.month),day(d.day){}; |
| |
| Date(char *ps); |
| void print_ymd(); |
| |
| ~Date() { }; |
| |
| }; |
# 實際意義的析構函數
機器人的特徵
姓名
型號
整數:待翻譯的整數
翻譯的英文句子字符串:字符指針,句子有長有短
……
機器人的功能
翻譯整數函數:形成英文字符串,並將字符串指針返回
構造函數
設置函數
輸出英文句子函數
析構函數
# 機器人類實踐
| class robot |
| { |
| private: |
| |
| char name[20]; |
| |
| char type[20]; |
| public: |
| |
| robot() |
| { |
| strcpy(name,"XXXXXX"); |
| strcpy(type,"XXXXXX"); |
| } |
| |
| void set(charn[],chart[]) |
| { |
| strcpy(name,n); |
| strcpy(type,t); |
| } |
| |
| void out(inta); |
| |
| void tran_int(intn); |
| |
| ~robot(){}; |
| }; |
| |
| |
| |
| static char *num1[]= |
| { |
| "","one ","two ","three ","four ","five ","six ","seven ","eight ", |
| "nine ","ten ","eleven ","twelve ", "thirteen ","fourteen ", |
| "fifteen ","sixteen ","seventeen ","eighteen ","nineteen " |
| }; |
| |
| static char *num10[]= |
| { |
| "","","twenty ","thirty ","forty ","fifty ","sixty ","seventy ", |
| "eighty ","ninety " |
| }; |
| |
| |
| void robot::out(int a) |
| { |
| int b=a%100; |
| |
| |
| if(a/100!=0) |
| { |
| cout<<num1[a/100]<<"hundred "; |
| if(b!=0) |
| { |
| cout<<"and "; |
| } |
| } |
| |
| if(b<20) { |
| cout<<num1[b]; |
| } |
| |
| else |
| { |
| |
| cout<<num10[b/10]; |
| |
| if(b%10!=0) |
| { |
| cout<<"\b-"<<num1[b%10]; |
| } |
| } |
| } |
| |
| |
| void robot::tran_int(int n) |
| { |
| if(n>1999999999) |
| { |
| cout<<"dev C++無法處理大於1999999999位的數!"<<endl; |
| } |
| else |
| { |
| |
| int a=n/1000000000, |
| b=(n%1000000000)/1000000, |
| c=(n%1000000)/1000, |
| d=n%1000; |
| |
| if(a!=0) |
| { |
| out(a); |
| cout<<"billion "; |
| } |
| if(b!=0) |
| { |
| out(b); |
| cout<<"million "; |
| } |
| if(c!=0) |
| { |
| out(c); |
| cout<<"thousand "; |
| } |
| if(d!=0) |
| { |
| |
| if(d<100&&(a!=0||b!=0||c!=0)) { |
| cout<<"and "; |
| } |
| out(d); |
| } |
| cout<<endl; |
| } |
| } |
| |
| int main() { |
| int n; |
| cout<<"請輸入 n:"; |
| cin>>n; |
| cout<<n<<endl; |
| robot brown; |
| brown.tran_int(n); |
| return 0; |
| } |
# 改良機器人類
| class robot |
| { |
| private: |
| |
| char name[20]; |
| |
| char type[20]; |
| |
| int num; |
| |
| char *ps; |
| public: |
| |
| robot() |
| { |
| strcpy(name,"XXXXXX"); |
| strcpy(type,"XXXXXX"); |
| num=0; |
| ps=new char[5]; |
| strcpy(ps,"zero"); |
| } |
| |
| |
| void set(charn[],chart[]) |
| { |
| strcpy(name,n); |
| strcpy(type,t); |
| } |
| |
| |
| char *out(int a); |
| |
| |
| char *tran_int(int n); |
| |
| |
| void print_num(); |
| |
| |
| ~robot(){ |
| |
| delete [] ps; |
| }; |
| }; |
| |
| |
| |
| static char *num1[]= |
| { |
| "","one ","two ","three ","four ","five ","six ","seven ","eight ", |
| "nine ","ten ","eleven ","twelve ", "thirteen ","fourteen ", |
| "fifteen ","sixteen ","seventeen ","eighteen ","nineteen " |
| }; |
| |
| static char *num10[]= |
| { |
| "","","twenty ","thirty ","forty ","fifty ","sixty ","seventy ", |
| "eighty ","ninety " |
| }; |
| |
| |
| char *robot::out(int a) |
| { |
| |
| char k[1000]=""; |
| int b=a%100; |
| |
| |
| if(a/100!=0) |
| { |
| |
| strcat(k,num1[a/100]); |
| strcat(k,"hundred "); |
| if(b!=0) { |
| strcat(k,"and "); |
| } |
| } |
| |
| if(b<20) { |
| strcat(k,num1[b]); |
| } |
| |
| else |
| { |
| |
| strcat(k,num10[b/10]); |
| |
| if(b%10!=0) |
| { |
| strcat(k,"\b-"); |
| strcat(k,num1[b%10]); |
| } |
| } |
| |
| |
| char *p=new char[strlen(k)+1]; |
| |
| |
| strcpy(p,k); |
| return p; |
| } |
| |
| |
| char *robot::tran_int(int n) |
| { |
| char *p; |
| char kk[1000]=""; |
| if(n>1999999999) |
| { |
| strcpy(kk,"dev C++無法處理太大的數!\n"); |
| } |
| else |
| { |
| |
| int a=n/1000000000, |
| b=(n%1000000000)/1000000, |
| c=(n%1000000)/1000, |
| d=n%1000; |
| |
| if(a!=0) |
| { |
| p=out(a); |
| strcpy(kk,p); |
| strcat(kk,"billion "); |
| delete [] p; |
| } |
| if(b!=0) |
| { |
| p=out(b); |
| strcat(kk,p); |
| strcat(kk,"million "); |
| delete [] p; |
| } |
| if(c!=0) |
| { |
| p=out(c); |
| strcat(kk,p); |
| strcat(kk,"thousand "); |
| delete [] p; |
| } |
| if(d!=0) |
| { |
| |
| if(d<100&&(a!=0||b!=0||c!=0)) { |
| strcat(kk,"and "); |
| } |
| p=out(d); |
| strcat(kk,p); |
| delete [] p; |
| } |
| p=new char[strlen(kk)+1]; |
| strcpy(p,kk); |
| return p; |
| } |
| } |
| |
| |
| void robot::set(char n[],char t[],int m) |
| { |
| strcpy(name,n); |
| strcpy(type,t); |
| |
| if(num==m) { |
| |
| return; |
| } |
| else |
| { |
| num=m; |
| delete [] ps; |
| } |
| |
| if(num>0) { |
| char *tp=tran_int(num); |
| ps=new char[strlen(tp)+1]; |
| strcpy(ps,tp); |
| delete [] tp; |
| } |
| else if(num==0) |
| { |
| ps=new char[5]; |
| strcpy(ps,"zero"); |
| } |
| else |
| { |
| ps=new char[13]; |
| strcpy(ps, "負數不能翻譯"); |
| } |
| } |
| |
| int main() { |
| robot brown; |
| brown.print_num(); |
| int n; |
| cout<<"請輸入n:"; |
| cin>>n; |
| brown.set("brown","800#",n); |
| brown.print_num(); |
| return 0; |
| } |
# 對象與指標
| class Person |
| { |
| private: |
| char Name[9]; |
| char Sex; |
| int Age; |
| char Pid[19]; |
| char *Addr; |
| public: |
| Person() |
| { |
| strcpy(Name,"xxxxxxxx"); |
| Age = 0; |
| Sex = 'x'; |
| strcpy(Pid,"xxxxxxxxxxxxxxxxxx"); |
| Addr=NULL; |
| } |
| Person(char *N, int A, char S,char *P,char *Ad) |
| { |
| strcpy(Name,N); |
| Age = A; |
| Sex = S; |
| strcpy(Pid,P); |
| int L=strlen(Ad); |
| Addr=new char[L+1]; |
| strcpy(Addr,Ad); |
| } |
| ~Person() |
| { |
| cout<<"Now destroying Person"<<Name<<endl; |
| delete [] Addr; |
| } |
| void Register( char *name, int age, char sex,char *pid,char *addr); |
| void ShowMe(); |
| }; |
| |
| |
| void Person::Register(char *name,int age,char sex,char *pid,char *addr) |
| { |
| strcpy(Name,name); |
| Age = age; |
| Sex = sex; |
| strcpy(Pid,pid); |
| if(Addr!=NULL) { |
| delete [] Addr; |
| } |
| int L=strlen(addr); |
| Addr=new char[L+1]; |
| strcpy(Addr,addr); |
| } |
| void Person::ShowMe() |
| { |
| cout<<Name<<" "<<Age<<" "<<Sex<<" "<<Pid<<" "; |
| if(Addr!=NULL) { |
| cout<<Addr; |
| } |
| cout<<endl; |
| } |
| |
| |
| int main() |
| { |
| Person person1; |
| Person person2("張三",19,'m',"610103199409192839","嘉義縣"); |
| Person person3; |
| cout<<"person1: "; |
| person1.ShowMe(); |
| cout<<"person2: "; |
| person2.ShowMe(); |
| person3.Register("李四",29,'w',"610103198409192493","台北市"); |
| cout<<"person3: "; |
| person3.ShowMe(); |
| person2.Register("趙五",29,'w',"610103198409152127","台南市"); |
| cout<<"person2: "; |
| person2.ShowMe(); |
| return 0; |
| } |
# 指向對象的指標
| <類名> *<指標變數表>; |
| |
| |
| Person person1("Zrn",19,'f'); |
| Person *ptr=&person1; |
| ptr->ShowMe(); |
# 動態存儲
| <對象指標>=new <類名>(<名字初始化值>); |
| delete <名字指標>; |
| |
| |
| Person *p=new Person; |
| delete p; |
# 修改版日期類
| #include<iostream> |
| using namespace std; |
| class Date |
| { |
| public: |
| int year,month,day; |
| void init(int y,int m,int k); |
| void print_ymd(); |
| }; |
| |
| void Date::init(int yy,int mm,int dd) |
| { |
| month = mm; |
| year = yy; |
| day = dd; |
| } |
| void Date::print_ymd() |
| { |
| cout<<year<<"-"<<month<<"-"<<day<<endl; |
| } |
| |
| int main() |
| { |
| Date date1; |
| Date *p1 = &date1; |
| p1->init(2006,5,13); |
| p1->print_ymd(); |
| int *p2 = &date1.year; |
| cout << *p2 <<endl; |
| void (Date::*p3)(int ,int ,int); |
| void (Date::*p4)(); |
| p3 = Date::init; |
| p4 = Date::print_ymd; |
| (date1.*p3)(2006,4,8); |
| (date1.*p4)(); |
| return 0; |
| } |
# 修改 Person 類
| #include<iostream> |
| #include<string.h> |
| using namespace std; |
| class Person |
| { |
| private: |
| char Name[9]; |
| char Sex; |
| int Age; |
| public: |
| Person() |
| { |
| strcpy(Name,"XXX"); |
| Age = 0; |
| Sex = ' '; |
| } |
| ~Person() |
| { |
| cout<<"Now destroying Person"<<endl; |
| } |
| void Register( char *name, int age, char sex); |
| void ShowMe(); |
| }; |
| |
| void Person::Register(char *name,int age,char sex) |
| { |
| strcpy(Name,name); |
| Age = age; |
| Sex = sex; |
| } |
| void Person::ShowMe() |
| { |
| cout<<Name<<'\t'<<Age<<'\t'<<Sex<<endl; |
| } |
| |
| int main() |
| { |
| Person *p1,*p2; |
| p1=new Person; |
| cout << "person1: \t"; |
| p1->ShowMe(); |
| p1->Register("Zhang3", 19, 'm'); |
| cout << "person1: \t"; |
| p1->ShowMe(); |
| |
| p2=new Person; |
| cout << "person2: \t"; |
| p2->ShowMe(); |
| *p2 = *p1; |
| cout << "person2: \t"; |
| p2->ShowMe(); |
| |
| delete p1; |
| delete p2; |
| return 0; |
| } |
# this
指標
- 每一個類的成員函數都包含一個指向本類對象的指針,指針名為
this
。 - 該指針指向本類對象的起始地址
this
是指針, *this
就是對象(本對象) - 訪問成員
this->成員
、 (*this).成員
.
運算符優先級比較高,故需要使用 ()
| #include <iostream> |
| using namespace std; |
| class Test |
| { |
| int x; |
| public: |
| Test( int = 0 ); |
| void print(); |
| }; |
| |
| |
| Test::Test(int a) |
| { |
| x = a; |
| } |
| |
| void Test::print() |
| { |
| cout << " x = " << x <<endl; |
| cout << "this->x = " << this->x << endl; |
| cout << "(*this).x = " << ( *this ).x << endl; |
| } |
| |
| int main() |
| { |
| Test testObject( 12 ); |
| testObject.print(); |
| return 0; |
| } |
- 當類中數據成員名與成員函數中的形參名相同時,用
this
指針加以區分
| class Time |
| { |
| private: |
| int hour,minute,second; |
| public: |
| void set(int hour,int minute,int second) |
| { |
| this->hour = hour; |
| this->minute = minute; |
| this->second = second; |
| } |
| } |
| |
| Fraction::Fraction(int a,int b) |
| { |
| set(a,b); |
| } |
| |
| void Fraction::set(int a,int b) |
| { |
| this->a=a; |
| this->b=b; |
| } |
| |
| |
| Fraction Fraction::add(Fraction u) |
| { |
| int tmp; |
| Fraction v; |
| v.a=a*u.b+b*u.a; |
| v.b=b*u.b; |
| tmp=divisor(v.a ,v.b); |
| v.a=v.a/tmp; |
| v.b=v.b/tmp; |
| return v; |
| } |
- 成員函數需要返回指針或本對象時
| |
| Fraction Fraction::add(Fraction u) { |
| int tmp; |
| |
| a=a*u.b+b*u.a; |
| b=b*u.b; |
| tmp=divisor(a ,b); |
| a=a/tmp; |
| b=b/tmp; |
| return *this; |
| } |