C++ 中提到了構造函數、拷貝構造函數、析構函數這幾個概念,在此我将對這幾個概念進行簡單的解釋及總結。寫的不全,請見諒
一、構造函數
1、構造函數:一種特殊的成員函數,用來初始化對象。
2、構造函數的特點: a、函數名和類名相同。
b、無傳回值,沒有類型。(實際傳回目前對象的引用)
c、構造函數不需要使用者調用,也不能被使用者調用,隻會在新的對象被建立時,由編譯器自動調用,且在對象的生命周期内僅調用一次,以保證每個資料成員都有一個合适的初始值。
d、有初始化清單(可以不用,隻有構造函數有初始化清單)。
e、構造函數可以重載,實參決定調用哪個構造函數。
f、如果沒有顯示定義,系統會提供一個預設的構造函數。
g、無參構造函數和帶有預設值的構造函數都被認為是預設構造函數,而且預設構造函數隻能有一個。
h、構造函數不能用const和volatile來修飾。
3、使用構造函數需了解一下問題:
a、構造函數不能用const修飾的原因:構造函數的作用是初始化對象,如果用const修飾構造函數,之後不能對該對象重新指派。
b、什麼情況下系統會合成一個預設構造函數?
有兩個類,A和B,B類中含有A類的對象,A中顯式定義了構造函數,B中無構造函數,此時,系統會在B類中合成一個預設構造函數。
class A
{
public:
A();
};
class B
{
public:
A a;
char * ptr;
};
int main()
{
B b;
return 0;
}
c、成員初始化清單隻提供該類資料化成員的初始化,而在構造函數體内對資料成員設定值失憶個指派操作。
eg:
<span style="font-size:14px;">#include<iostream>
#include<stdio.h>
using namespace std;
class Time //聲明Time類
{
public: //公有函數
Time() //定義構造成員函數(函數名與類名相同)
{
hour = 0; //利用構造函數對對象中的資料成員賦初始值
minute = 0;
second = 0;
}
void set_time(); //成員函數聲明
void show_time(); //成員函數聲明
private: //私有資料
int hour; //定義辨別符
int minute;
int second;
};
void Time::set_time() //定義成員函數,向資料成員指派
{
cin >> hour;
cin >> minute;
cin >> second;
}
void Time::show_time() //定義成員函數,輸出資料成員的值
{
cout << hour << ":" << minute << ":" << second << endl;
}
int main()
{
Time t1; //建立對象t1,同時調用構造函數t1.Time()
Time t2; //建立對象t2,同時調用構造函數t2.Time()
t1.set_time(); //對t1的資料成員指派
t1.show_time();//顯示t1的資料成員的值
t2.set_time();//對t2的資料成員指派
t2.show_time();//顯示t2的資料成員的值
system("pause");
return 0;
}</span>
二、拷貝構造函數
1、拷貝構造函數:一種特殊的構造函數,隻有一個形參,而且該形參是對本類類型對象的引用,這樣的構造函數稱為拷貝構造函數。
2、拷貝構造函數的特點:a、它是構造函數的重載。
b、隻有一個參數。
c、由普通構造函數和指派操作符共同實作。
d、它的參數必須使用同類型對象的引用傳遞。
e、如果沒有顯式定義,系統會自動合成一個預設的拷貝構造函數。預設的拷貝構造函數會依次拷貝類的資料成員完成初始化。
3、拷貝構造函數的使用場景: a、對象執行個體化對象
Time t1(21,55,32);
Time t2(t1);
b、傳值方式作為函數的參數
void test(cost Time time)
{}
c、傳值方式作為函數的傳回值
Time test()
{
Time time;
return time;
}
4、需了解:
拷貝構造函數的參數必須使用同類型對象的引用傳遞的原因:避免拷貝構造函數無限制的遞歸下去。
三、析構函數
1、析構函數:析構函數名也與類名相同,隻是在函數名前面加一個位取反符~,例~Time(),以差別構造函數。
2、析構函數的特點:a、析構函數與構造函數作用相反。
b、析構函數無參數,無傳回值。
c、一個類有且隻有一個析構函數。若未顯式定義,系統會生成預設的析構函數。
d、對象生命周期結束時,C++編譯系統自動調用析構函數。
e、析構函數體内并不是删除對象,而是做一些清理工作。
3、需了解:
a、由于析構函數沒有函數參數,是以不能被重載。
b、系統自動生成的析構函數隻是徒有析構函數的名稱和形式,實際上什麼操作都不進行。要讓析構函數完成任何工作,都必須在定義的析構函數中指定。
eg:
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
class student//聲明一個類
{
private://私有部分
int num;
char name[10];
char sex;
public://公用部分
student(int n, char nam[], char s)//構造函數
{
num = n;
strcpy(name,nam);
sex = s;
cout << "Constructor called." << endl;
}
~student() //析構函數
{
cout << "Distructor called." << endl;
}
void display()//成員函數,輸出對象的資料
{
cout << "num:" << num <<endl ;
cout << "name:" <<name<<endl;
cout << "sex:" << sex << endl;
}
};
int main()
{
student stud1(10010, "xue", 'f');//建立對象stud1
student stud2(10011, "jia", 'm');//建立對象stud2
stud1.display();//輸出學生1的資料
stud2.display();//輸出學生2的資料
system("pause");
return 0;
}