C++之类与对象(2)
接著上一節,今天講C++中類的構造函數與析構函數,對象的賦值與復制.
1.用過C#語言的人,都知道構造函數是一種特殊的成員函數,它主要用于對對象分配空間,進行初始化。構造函數的名字必須與類名相同。可以有任何類型的參數,但不返回任何值,是在建立對象時自動執行的。和上一節一樣,還是用Kid類來說明。
1 class Kid2 {
3 private:
4 int age;
5 char*name;
6 char*sex;
7 public:
8 Kid(int age,char*name,char*sex);
9 void showKid();
10 };
11
12 Kid::Kid(int age,char*name,char*sex)
13 {
14 Kid::age=age;
15 Kid::name=name;
16 Kid::sex=sex;
17 }
18
19 void Kid::showKid()
20 {
21 cout<<"姓名:"<<name<<endl<<"年齡:"<<age<<endl<<"性別:"<<sex<<endl;
22 }
接下來,建立對象并初始化:Kid kid(10,"rookie_j","男");另外一種使用new運算符動態建立對象:Kid *ptr=new Kid(10,"rookie_j","男");通過指針變量ptr來訪問:ptr->showKid();當我們用new建立對象時,當不再使用它時,要用delete運算符釋放它:delete ptr;和不同成員函數一樣,如果構造函數定義在類體內部,則作為內聯函數處理;
在聲明類時,對數據成員的初始化一般在構造函數中用賦值語句進行,但C++還提供了另外一種初始化數據成員的方法——用成員初始化表來實現對數據成員的初始化。它的一般形式為:類名::構造函數名([參數表]):[(成員初始化表)];成員初始化表的形式為:成員名1(初始值1),成員名2(初始值2),成員名2(初始值2);比如:
Kid::Kid(int age,char *name,char *sex):age(age),name(name),sex(sex){};
接下來講一下析構函數:在我第一次在C++里看到這個名詞時,感覺這個知識點很深奧,結果看了以后,其實很簡單。它的作用和構造函數剛好相反,用于撤銷對象,如:釋放分配給對象的內存空間。析構函數和構造函數名相同,但在其前面要加~符號,析構函數沒有參數,也沒有返回值,且不能重載,因此一個類中只有一個析構函數。以下三種情況,當對象的生命周期結束時,析構函數會被自動調用:(1)定義了全局對象,則在程序流程離開其作用域(如:main函數結束或調用Exit)時,調用該全局對象的析構函數;(2)對象被定義在函數體里,則當這個函數執行完后,該對象釋放,析構函數被自動調用;(3)若一個對象使用new運算符動態創建的,在使用delete運算符釋放它時,會自動調用析構函數;
View Code 1 #include "stdafx.h"2 #include <iostream>
3
4 usingnamespace std;
5
6 class Kid
7 {
8 private:
9 int age;
10 char*name;
11 char*sex;
12 public:
13 Kid(int age,char*name,char*sex);
14 ~Kid();
15 void showKid();
16 };
17
18
19 Kid::Kid(int age,char*name,char*sex)
20 {
21 Kid::age=age;
22 Kid::name=newchar[strlen(name)];
23 strcpy(Kid::name,name);
24 Kid::sex=newchar[strlen(sex)];
25 strcpy(Kid::sex,sex);
26 }
27
28 Kid::~Kid()
29 {
30 cout<<"dispose object kid"<<endl;
31 delete []name;
32 delete []sex;
33 }
34
35 void Kid::showKid()
36 {
37 cout<<"姓名:"<<name<<endl<<"年齡:"<<age<<endl<<"性別:"<<sex<<endl;
38 }
39
40
41 int main()
42 {
43 Kid kid(10,"rookie_j","男");
44 kid.showKid();
45
46 Kid *ptr=new Kid(10,"rookie_x","女");
47 ptr->showKid();
48
49 delete ptr;
50
51 return0;
52 }
結果:
如果沒有給類定義構造函數,則編譯系統自動地生成一個默認的構造函數,比如在Kid類中編譯系統會為其產生一個Kid::Kid(){};構造函數,這個默認的構造函數只能給對象開辟存儲空間,不能給數據成員賦值,這時數據成員的初值就是隨機數。對沒有定義構造函數的類,其公有數據成員可以用初始化值表進行初始化,如:
1 class Kid2 {
3 public:
4 int age;
5 char*name;
6 char*sex;
7 };
8
9 int main()
10 {
11
12 Kid kid={10,"Rookie_j","男"};
13 cout<<"姓名:"<<kid.name<<endl<<"年齡:"<<kid.age<<endl<<"性別:"<<kid.sex<<endl;
14
15 return0;
16 }
但只要一個類定義了構造函數,系統將不再給它提供默認構造函數;另外還有默認的析構函數(Kid::~Kid(){}),一般來說默認的析構函數就能滿足要求,但對一些需要做一些內部處理的則應該顯式定義析構函數。帶默認參數的構造函數和之前所說的帶參數的成員函數是一樣的,對于構造函數的重載,在這里我就不多說了,只想強調一點,如果是無參的構造函數創建對象,應該使用"類名 對象名"的形式,而不是"類名 對象名()";
2.對象的賦值其實和變量的賦值差不多,也是用賦值運算符=進行的,只不過進行賦值的兩個對象的類型必須相同,對象之間的賦值只是數據成員的賦值,而不對成員函數賦值;
?
View Code 1 #include "stdafx.h"2 #include <iostream>
3
4 usingnamespace std;
5
6 class Kid
7 {
8 private:
9 int age;
10 char*name;
11 char*sex;
12 public:
13 Kid(int age,char*name,char*sex);
14 Kid(){ };
15 ~Kid();
16 void showKid();
17 };
18
19
20 Kid::Kid(int age,char*name,char*sex)
21 {
22 Kid::age=age;
23 Kid::name=newchar[strlen(name)];
24 strcpy(Kid::name,name);
25 Kid::sex=newchar[strlen(sex)];
26 strcpy(Kid::sex,sex);
27 }
28
29 Kid::~Kid()
30 {
31 cout<<"dispose object kid"<<endl;
32 delete []name;
33 delete []sex;
34 }
35
36 void Kid::showKid()
37 {
38 cout<<"姓名:"<<name<<endl<<"年齡:"<<age<<endl<<"性別:"<<sex<<endl;
39 }
40
41 int main()
42 {
43 Kid kid(10,"rookie_j","男"),kid2;
44 kid.showKid();
45
46 kid2=kid;
47 kid2.showKid();
48
49 return0;
50 }
?
結果:
拷貝構造函數是一種特殊的構造函數,其形參是類對象的引用。它主要用于在建立一個新的對象時,使用已經存在的對象去初始化這個新對象。拷貝構造函數也是構造函數,所以函數名必須與類名相同,參數只有一個就是同類對象的引用,每個類必須要有一個拷貝構造函數。如果程序員自己不定義拷貝構造函數,系統會自動產生一個默認拷貝構造函數。調用拷貝構造函數的形式有代入法:類名 對象2(對象1)和賦值法:類名 對象2=對象1;
View Code 1 #include "stdafx.h"2 #include <iostream>
3
4 usingnamespace std;
5
6 class Kid
7 {
8 private:
9 int age;
10 char*name;
11 char*sex;
12 public:
13 Kid(int age,char*name,char*sex);
14 Kid(const Kid &kid);
15 ~Kid();
16 void showKid();
17 };
18
19
20 Kid::Kid(int age,char*name,char*sex)
21 {
22 Kid::age=age;
23 Kid::name=newchar[strlen(name)];
24 strcpy(Kid::name,name);
25 Kid::sex=newchar[strlen(sex)];
26 strcpy(Kid::sex,sex);
27 }
28
29 Kid::Kid(const Kid &kid)
30 {
31 Kid::age=kid.age*2;
32 Kid::name=newchar[strlen(kid.name)];
33 strcpy(Kid::name,kid.name);
34 Kid::sex=newchar[strlen(kid.sex)];
35 strcpy(Kid::sex,kid.sex);
36 }
37
38 Kid::~Kid()
39 {
40 cout<<"dispose object kid"<<endl;
41 delete []name;
42 delete []sex;
43 }
44
45 void Kid::showKid()
46 {
47 cout<<"姓名:"<<name<<endl<<"年齡:"<<age<<endl<<"性別:"<<sex<<endl;
48 }
49
50 int main()
51 {
52 Kid kid(10,"rookie_j","男");
53 kid.showKid();
54
55 Kid kid2(kid);
56 kid2.showKid();
57
58 Kid kid3=kid2;
59 kid3.showKid();
60
61 return0;
62 }
結果:
?
同樣的默認的拷貝構造函數:復制出與源對象的數據成員的值一樣的新對象。調用拷貝構造函數的3種情況:(1)Kid kid2(kid1)或Kid kid2=kid1;(2)函數的形參是類的對象:fun(Kid kid){kid.showKid();}; int main(){Kid kid(10,"Rookie_j","男");fun(kid);return 0;};(3)函數返回值為類的對象:Kid fun(){Kid kid(10,"Rookie_j","男"); return kid;} int main(){ Kid kid; kid=fun();kid.showKid();return 0;};
3.最后還是一樣用一個實例來總結一下今天所說的內容(開發工具:vs2010):
View Code 1 #include "stdafx.h"2 #include <iostream>
3
4 usingnamespace std;
5
6 class Kid
7 {
8 private:
9 int age;
10 char*name;
11 char*sex;
12 public:
13 Kid(int age,char*name,char*sex);
14 Kid(const Kid &kid); //自定義拷貝函數
15 ~Kid();
16 void showKid();
17 };
18
19
20 Kid::Kid(int age,char*name,char*sex)
21 {
22 Kid::age=age;
23 Kid::name=newchar[strlen(name)];
24 strcpy(Kid::name,name);
25 Kid::sex=newchar[strlen(sex)];
26 strcpy(Kid::sex,sex);
27 }
28
29 //Kid::Kid(int age,char *name,char *sex):age(age),name(name),sex(sex) //用成員初始化表對數據成員初始化
30 //{
31 //
32 //}
33
34 Kid::Kid(const Kid &kid)
35 {
36 Kid::age=kid.age*2;
37 Kid::name=newchar[strlen(kid.name)];
38 strcpy(Kid::name,kid.name);
39 Kid::sex=newchar[strlen(kid.sex)];
40 strcpy(Kid::sex,kid.sex);
41 }
42
43 Kid::~Kid() //自定義析構函數
44 {
45 cout<<"dispose object kid"<<endl;
46 delete []name; //delete運算符釋放存儲空間
47 delete []sex;
48 }
49
50 void Kid::showKid()
51 {
52 cout<<"孩子:"<<endl<<"姓名:"<<name<<endl<<"年齡:"<<age<<endl<<"性別:"<<sex<<endl;
53 }
54
55 class Car
56 {
57 public:
58 char*no;
59 char*brand;
60 int speed;
61 void showCar();
62 ~Car(){};//仿默認析構
63 };
64
65
66
67 void Car::showCar()
68 {
69 cout<<"汽車:"<<endl<<"號碼:"<<no<<endl<<"品牌:"<<brand<<endl<<"速度:"<<speed<<"km/h"<<endl;
70 }
71
72 int main()
73 {
74 Kid kid(10,"rookie_j","男");
75 kid.showKid();
76
77 cout<<"--------------------"<<endl;
78
79 Kid kid2(kid); //代入法調用拷貝構造函數
80 kid2.showKid();
81
82 cout<<"--------------------"<<endl;
83
84 Kid kid3=kid2; //賦值法調用拷貝構造函數
85 kid3.showKid();
86
87 cout<<"--------------------"<<endl;
88
89 Kid *ptr=new Kid(10,"rookie_x","女"); //使用new運算符動態創建對象
90 ptr->showKid();
91
92 cout<<"--------------------"<<endl;
93
94 //delete ptr; //釋放對象所占的存儲空間
95
96 Car car={"8888888","Benz",200},car2;//只有沒定義構造函數的類,才能用初始值表初始化公有數據成員,默認構造
97 car.showCar();
98
99
100 cout<<"--------------------"<<endl;
101
102 car2=car;//默認拷貝構造函數或car2(car)
103 car2.showCar();
104
105 cout<<"--------------------"<<endl;
106
107 return0;
108 }
結果:
但在運行的時候,發現一個問題如果把delete ptr; 這句的注釋去掉,結果汽車的情況就顯示不出來了;
結果:
不知道為什么?求助各位大俠!
轉載于:https://www.cnblogs.com/CaiNiaoZJ/archive/2011/07/24/2115041.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的C++之类与对象(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mongodb和SQL语句对应查找表
- 下一篇: 温湿度设备开发总结