C++的構(gòu)造函數(shù)的作用:初始化類對象的數(shù)據(jù)成員。
即類的對象被創(chuàng)建的時候,編譯系統(tǒng)對該對象分配內(nèi)存空間,并自動調(diào)用構(gòu)造函數(shù),完成類成員的初始化。
構(gòu)造函數(shù)的特點:以類名作為函數(shù)名,無返回類型。
常見的構(gòu)造函數(shù)有三種寫法:
- 無參構(gòu)造函數(shù)
- 一般構(gòu)造函數(shù)
- 復(fù)制構(gòu)造函數(shù)
C++的構(gòu)造函數(shù)可以有多個,創(chuàng)建對象時編譯器會根據(jù)傳入的參數(shù)不同調(diào)用不同的構(gòu)造函數(shù)。
1、無參構(gòu)造函數(shù)
如果創(chuàng)建一個類,沒有寫任何構(gòu)造函數(shù),則系統(tǒng)會自動生成默認(rèn)的無參構(gòu)造函數(shù),且此函數(shù)為空。
默認(rèn)構(gòu)造函數(shù)(default constructor)就是在沒有顯式提供初始化式時調(diào)用的構(gòu)造函數(shù)。如果定義某個類的變量時沒有提供初始化時就會使用默認(rèn)構(gòu)造函數(shù)。
但只要有下面某一種構(gòu)造函數(shù),系統(tǒng)就不會再自動生成這樣一個默認(rèn)的構(gòu)造函數(shù)。如果希望有一個這樣的無參構(gòu)造函數(shù),則需要顯示地寫出來。
#include <IOStream>
using namespace std;
class Student {
public:
int m_age;
int m_score;
// 1. 無參構(gòu)造函數(shù)
Student() {
m_age = 10;
m_score = 99;
cout << "1. 無參構(gòu)造函數(shù)" << endl;
}
};
2、一般構(gòu)造函數(shù)
一般構(gòu)造函數(shù)有兩種寫法:
- 初始化列表方式:以一個冒號開始,接著是以逗號分隔的數(shù)據(jù)成員列表,每個數(shù)據(jù)成員后面跟一個放在括號中的初始化值。
- 內(nèi)部賦值方式:正常函數(shù)的賦值。
#include <iostream>
using namespace std;
class Student {
public:
int m_age;
int m_score;
// 2. 一般構(gòu)造函數(shù)
// 初始化列表方式
Student(int age, int score) :
m_age(age),
m_score(score)
{}
// 內(nèi)部賦值方式
Student(int age, int score) {
m_age = age;
m_score = score;
}
};
C++規(guī)定,對象的成員變量的初始化動作發(fā)生在進(jìn)入構(gòu)造函數(shù)本體之前。也就是說采用初始化列表的話,構(gòu)造函數(shù)本體實際上不需要有任何操作,因此效率更高。
一般構(gòu)造函數(shù)可以有多種參數(shù)形式,即一個類可以有多個一般構(gòu)造函數(shù),前提是參數(shù)的個數(shù)或者類型不同(C++的函數(shù)重載機(jī)制)。
C++覆蓋和重載的區(qū)別
#include <iostream>
using namespace std;
class Student {
public:
int m_age;
int m_score;
// 2. 一般構(gòu)造函數(shù)
Student(int age, int score) {
m_age = age;
m_score = score;
cout << "2.1 一般構(gòu)造函數(shù)" << endl;
}
Student(int age) {
m_age = age;
cout << "2.2 一般構(gòu)造函數(shù)" << endl;
}
};
3、復(fù)制構(gòu)造函數(shù)
復(fù)制構(gòu)造函數(shù),也稱為拷貝構(gòu)造函數(shù)。
復(fù)制構(gòu)造函數(shù)參數(shù)為類對象本身的引用,根據(jù)一個已存在的對象復(fù)制出一個新的對象,一般在函數(shù)中會將已存在對象的數(shù)據(jù)成員的值復(fù)制一份到新創(chuàng)建的對象中。
#include <iostream>
using namespace std;
class Student {
public:
int m_age;
int m_score;
// 3. 復(fù)制構(gòu)造函數(shù)
Student(Student& s) {
m_age = s.m_age;
m_score = s.m_score;
cout << "3. 復(fù)制構(gòu)造函數(shù)" << endl;
}
};
注意:若沒有顯示定義復(fù)制構(gòu)造函數(shù),則系統(tǒng)會默認(rèn)創(chuàng)建一個復(fù)制構(gòu)造函數(shù),當(dāng)類中有指針成員時,由系統(tǒng)默認(rèn)創(chuàng)建的復(fù)制構(gòu)造函數(shù)會存在“淺拷貝”的風(fēng)險,因此必須顯示定義復(fù)制構(gòu)造函數(shù)。
- 淺拷貝指的是在對對象復(fù)制時,只對對象中的數(shù)據(jù)成員進(jìn)行簡單的賦值,若存在動態(tài)成員,就是增加一個指針,指向原來已經(jīng)存在的內(nèi)存。這樣就造成兩個指針指向了堆里的同一個空間。當(dāng)這兩個對象生命周期結(jié)束時,析構(gòu)函數(shù)會被調(diào)用兩次,同一個空間被兩次free。
- 深拷貝就是對于對象中的動態(tài)成員,不是簡單的賦值,而是重新分配空間。
構(gòu)造函數(shù)的調(diào)用示例如下:
int main()
{
Student stu1; // 調(diào)用無參構(gòu)造函數(shù)
Student stu21(21, 20); // 調(diào)用一般構(gòu)造函數(shù)
Student stu22(22); // 調(diào)用一般構(gòu)造函數(shù)
Student stu3(stu1); // 調(diào)用復(fù)制構(gòu)造函數(shù)
return 0;
}






