C++默認(rèn)構(gòu)造函數(shù)詳解
一、類的默認(rèn)成員函數(shù)
- 當(dāng)你定義一個(gè)空類時(shí),編譯器并不會(huì)真的“空手而歸”。它會(huì)自動(dòng)為你生成6個(gè)(C++98)或更多(C++11后)特殊的成員函數(shù)。這些函數(shù)被稱為默認(rèn)成員函數(shù)。
- 他們分別是:
| 函數(shù) | 作用 |
|---|---|
| 默認(rèn)構(gòu)造函數(shù) | 初始化對象 |
| 析構(gòu)函數(shù) | 清理對象資源 |
| 拷貝構(gòu)造函數(shù) | 用已有對象初始化新對象 |
| 賦值運(yùn)算符重載 | 將已有對象賦值給另一對象 |
| 移動(dòng)構(gòu)造函數(shù)(C++11) | 用臨時(shí)對象“轉(zhuǎn)移”資源 |
| 移動(dòng)賦值運(yùn)算符(C++11) | 臨時(shí)對象賦值 |
- 如果沒有主動(dòng)聲明這些函數(shù),編譯器就會(huì)自動(dòng)生成一個(gè)默認(rèn)版本,即為默認(rèn)成員函數(shù)。
二、構(gòu)造函數(shù)的基本概念
- 構(gòu)造函數(shù)是類中一種特殊的成員函數(shù),它在對象創(chuàng)建時(shí)自動(dòng)調(diào)用,用于初始化對象的成員變量。
構(gòu)造函數(shù)的規(guī)則:
- 函數(shù)名與類名完全相同
- 沒有返回值
- 可以重載(可以有多個(gè)參數(shù)不同的構(gòu)造函數(shù))
- 對象創(chuàng)建時(shí)自動(dòng)執(zhí)行
三、默認(rèn)構(gòu)造函數(shù)的含義
- 默認(rèn)構(gòu)造函數(shù)是指可以無實(shí)參可調(diào)用的構(gòu)造函數(shù)。它包括兩種情況:
- 程序員定義的默認(rèn)構(gòu)造函數(shù):
- 程序員定義的無參構(gòu)造函數(shù)。
- 程序員定義的全缺省參數(shù)的構(gòu)造函數(shù)。
- 程序員沒有定義構(gòu)造函數(shù),編譯器自動(dòng)生成的隱式默認(rèn)構(gòu)造函數(shù)。
- 程序員定義的默認(rèn)構(gòu)造函數(shù):
class Student {
public:
// 無參構(gòu)造函數(shù)
Student() {
name = "無名";
age = 0;
}
private:
string name;
int age;
};
cpp
class Point {
public:
// 全缺省參數(shù)的構(gòu)造函數(shù)(也是默認(rèn)構(gòu)造函數(shù))
Point(int x = 0, int y = 0) : x(x), y(y) {}
private:
int x, y;
};四、編譯器自動(dòng)生成的默認(rèn)構(gòu)造函數(shù)
- 若程序員沒有實(shí)現(xiàn)構(gòu)造函數(shù),編譯器會(huì)為你生成一個(gè)隱式默認(rèn)構(gòu)造函數(shù)。
class Dog {
string name;
int age;
// 編譯器自動(dòng)生成 Dog() {}
};
這個(gè)隱式構(gòu)造函數(shù)會(huì)做什么?
- 對于內(nèi)置類型(int, char, 指針等):不做任何初始化(不同編譯器效果不同)。
- 對于自定義類型成員:調(diào)用它們各自的默認(rèn)構(gòu)造函數(shù)。
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A的構(gòu)造函數(shù)" << endl; }
};
class B {
int x; // 內(nèi)置類型,不會(huì)初始化(垃圾值)
A a; // 類類型,會(huì)調(diào)用A的默認(rèn)構(gòu)造函數(shù)
};
int main() {
B b; // 輸出:A的構(gòu)造函數(shù)(x保持隨機(jī))
}一旦你實(shí)現(xiàn)了構(gòu)造函數(shù),編譯器就不再生成默認(rèn)構(gòu)造函數(shù)
class Student {
public:
Student(string n) { name = n; } // 自定義構(gòu)造函數(shù)
private:
string name;
};
int main() {
Student s1("張三"); // 正確
// Student s2; // 錯(cuò)誤!沒有默認(rèn)構(gòu)造函數(shù)可用
}如果你既需要帶參構(gòu)造,又需要無參構(gòu)造,需要手動(dòng)提供默認(rèn)構(gòu)造函數(shù)。
五、默認(rèn)構(gòu)造函數(shù)的用途
1. 定義對象而不初始化
class Array {
int* data;
public:
Array() { data = nullptr; } // 允許定義空數(shù)組對象
};
Array arr; // 調(diào)用默認(rèn)構(gòu)造
2. 作為容器元素的默認(rèn)構(gòu)造要求
STL容器(如vector)在擴(kuò)容或創(chuàng)建元素時(shí),經(jīng)常需要元素的默認(rèn)構(gòu)造函數(shù)。
vector<Student> v(10); // 需要Student有默認(rèn)構(gòu)造函數(shù)
3. 繼承體系中基類的初始化
派生類構(gòu)造函數(shù)會(huì)自動(dòng)調(diào)用基類的默認(rèn)構(gòu)造函數(shù)(如果基類沒有默認(rèn)構(gòu)造,派生類必須顯式調(diào)用基類的帶參構(gòu)造)。
六、什么時(shí)候需要自定義默認(rèn)構(gòu)造函數(shù)?
| 情況 | 是否需要 |
|---|---|
| 類沒有指針成員,且成員都有合理的默認(rèn)值 | 不需要,編譯器生成即可 |
| 成員中需要分配資源 | 需要(在構(gòu)造中分配并初始化) |
| 需要給成員變量設(shè)置特定的初始值 | 需要 |
| 類有自定義的帶參構(gòu)造,但仍需無參創(chuàng)建對象 | 需要 |
class MyString {
char* buf;
public:
// 自定義默認(rèn)構(gòu)造:給指針一個(gè)安全的初始值
MyString() {
buf = new char[1];
buf[0] = '\0';
}
};七、C++11 的改進(jìn):default 和 delete
C++11允許你顯式要求編譯器生成默認(rèn)版本,或禁止某個(gè)構(gòu)造函數(shù)。
class Widget {
public:
Widget() = default; // 手動(dòng)要求編譯器生成默認(rèn)構(gòu)造
Widget(const Widget&) = delete; // 禁止拷貝構(gòu)造
};
八、一個(gè)完整的例子
#include <iostream>
#include <string>
using namespace std;
class Book {
public:
// 默認(rèn)構(gòu)造函數(shù)
Book() {
title = "未命名";
price = 0.0;
cout << "調(diào)用默認(rèn)構(gòu)造函數(shù)" << endl;
}
// 帶參構(gòu)造函數(shù)(不是默認(rèn)構(gòu)造)
Book(string t, double p) : title(t), price(p) {
cout << "調(diào)用帶參構(gòu)造函數(shù)" << endl;
}
void print() {
cout << "書名:" << title << ",價(jià)格:" << price << endl;
}
private:
string title;
double price;
};
int main() {
Book b1; // 調(diào)用默認(rèn)構(gòu)造
Book b2("C++教程", 59.9); // 調(diào)用帶參構(gòu)造
b1.print();
b2.print();
return 0;
}
輸出:
text
調(diào)用默認(rèn)構(gòu)造函數(shù)
調(diào)用帶參構(gòu)造函數(shù)
書名:未命名,價(jià)格:0
書名:C++教程,價(jià)格:59.9到此這篇關(guān)于C++:默認(rèn)構(gòu)造函數(shù)的文章就介紹到這了,更多相關(guān)C++:默認(rèn)構(gòu)造函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
QT利用QPdfWriter實(shí)現(xiàn)繪制PDF(支持表單輸出)
這篇文章主要為大家詳細(xì)介紹了QT如何利用QPdfWriter實(shí)現(xiàn)繪制PDF,并可以支持表單輸出。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-01-01
C++?Cartographer源碼中關(guān)于MapBuilder的聲明與構(gòu)造
這篇文章主要介紹了C++?Cartographer源碼中關(guān)于MapBuilder的聲明與構(gòu)造,前面已經(jīng)談到了Cartographer中添加軌跡的方法和傳感器的數(shù)據(jù)流動(dòng)走向。在添加軌跡的時(shí)候,除了添加位姿估計(jì)器還有采樣器,訂閱回調(diào)函數(shù)之外,最重要的是通過map_builder_bridge添加了一條軌跡2023-03-03

