目錄
一、類的6個默認成員函數
?二、構造函數
?構造函數概念
?構造函數的特點
?常見構造函數的幾種類型
三、析構函數
??????析構函數概念
?????析構函數的特點
?常見析構函數的幾種類型
四、溫馨提示
前言
? ? ? ? ?這一篇文章是上一篇的續(xù)集(這里有上篇鏈接)前面我們講了C語言的基礎知識,也了解了一些數據結構,并且講了有關C++的命名空間的一些知識點以及關于C++的缺省參數、函數重載,引用 和 內聯(lián)函數。也相信大家都掌握的不錯,接下來博主將會帶領大家繼續(xù)學習有關C++比較重要的知識點——類和對象。下面話不多說坐穩(wěn)扶好咱們要開車了。
一、類的6個默認成員函數
????????如果一個類中什么成員都沒有,簡稱為空類??疹愔姓娴氖裁炊紱]有嗎?并不是,任何類在什么都不寫時,編譯器會自動生成以下6個默認成員函數。默認成員函數:用戶沒有顯式實現(xiàn),編譯器會生成的成員函數稱為默認成員函數
????????1. 默認構造函數(Default Constructor):如果類沒有定義任何構造函數,編譯器會自動生成一個默認構造函數。默認構造函數沒有參數,用于創(chuàng)建一個對象時進行初始化操作。
????????2. 析構函數(Destructor):析構函數在對象被銷毀時調用,用于釋放對象所占用的資源,如釋放動態(tài)分配的內存、關閉文件等。析構函數沒有參數,且其名稱以波浪線(~)開頭,后跟類名。
????????3. 拷貝構造函數(Copy Constructor):拷貝構造函數用于將一個已經存在的對象的數據成員復制到另一個對象中。當使用一個對象初始化另一個對象、函數參數以值傳遞方式傳遞對象、或者以值返回對象時,拷貝構造函數會被自動調用??截悩嬙旌瘮涤幸粋€參數,類型為同類對象的引用。
????????4. 拷貝賦值運算符(Copy Assignment Operator):拷貝賦值運算符用于將一個已經存在的對象的數據成員復制到另一個對象中。當使用賦值運算符=給一個已經初始化的對象賦值時,拷貝賦值運算符會被自動調用??截愘x值運算符有一個參數,類型為同類對象的引用,返回類型為引用。
????????5. 移動構造函數(Move Constructor):移動構造函數用于將一個臨時對象或者將要被銷毀的對象的資源(如動態(tài)分配的內存)“移動”給另一個對象,避免了不必要的數據拷貝。移動構造函數有一個參數,類型為同類對象的引用。
????????6. 移動賦值運算符(Move Assignment Operator):移動賦值運算符用于將一個臨時對象或者將要被銷毀的對象的資源(如動態(tài)分配的內存)“移動”給另一個對象,避免了不必要的數據拷貝。移動賦值運算符有一個參數,類型為同類對象的引用,返回類型為引用。
????????需要注意的是:如果自定義了析構函數、拷貝構造函數、拷貝賦值運算符、移動構造函數或移動賦值運算符中的任何一個,編譯器將不再為該類生成相應的默認成員函數。
?二、構造函數
?構造函數概念
????????C++中的構造函數是一種特殊的成員函數,用于創(chuàng)建和初始化類的對象。構造函數在對象被創(chuàng)建時自動被調用,主要目的是為對象的數據成員提供初始值,確保對象在創(chuàng)建后處于合適的狀態(tài)。
?構造函數的特點
1. 構造函數的名稱必須與類名完全相同,并且沒有返回類型(連void也沒有)。
2. 構造函數可以有參數,用于在創(chuàng)建對象時提供初始化值。這些參數可以有默認值,也可以是任意類型。
3. 構造函數可以被重載,也就是可以定義多個具有相同名稱但參數列表不同的構造函數。這樣可以根據不同的初始化需求選擇合適的構造函數。
4. 在創(chuàng)建對象時,會自動調用與對象匹配的構造函數。也就是說,構造函數在對象被創(chuàng)建的時候自動被調用,無需手動調用。
5. 構造函數可以執(zhí)行一些必要的初始化操作,如動態(tài)分配內存、打開文件、初始化數據成員等。
?常見構造函數的幾種類型
1. 默認構造函數(Default Constructor)
????????沒有參數的構造函數,用于創(chuàng)建對象時提供默認的初始值。
2. 帶參構造函數(Parameterized Constructor)????????帶有參數的構造函數,用于根據提供的參數初始化對象的數據成員。
3. 復制構造函數(Copy Constructor)????????以一個同類對象作為參數,用于根據已有對象創(chuàng)建新的對象。
4. 移動構造函數(Move Constructor)????????以一個臨時對象或將要被銷毀的對象作為參數,用于“移動”資源(如動態(tài)分配的內存)而不是執(zhí)行數據拷貝。
5. 類型轉換構造函數(Conversion Constructor)????????以其他類型的對象作為參數,用于將其他類型的對象轉換為該類的對象。
????????構造函數在類的定義中是以公有(public)訪問權限聲明的,因為它們需要被外部代碼調用來創(chuàng)建對象。一個類可以有多個構造函數,并且可以選擇性地定義它們,如果沒有定義任何構造函數,編譯器會自動生成一個默認構造函數。
下面是一個簡單的示例,展示了一個類 ‘ Person ’ 的構造函數的定義和使用:
#include <iostream>
#include <string>
class Person {
public:
? ? // 默認構造函數
? ? Person() {
? ? ? ? name = "Unknown";
? ? ? ? age = 0;
? ? }
? ? // 帶參構造函數
? ? Person(const std::string& n, int a) {
? ? ? ? name = n;
? ? ? ? age = a;
? ? }
? ? // 打印信息的成員函數
? ? void printInfo() {
? ? ? ? std::cout << "Name: " << name << ", Age: " << age << std::endl;
? ? }
private:
? ? std::string name;
? ? int age;
};
int main() {
? ? // 使用默認構造函數創(chuàng)建對象
? ? Person p1;
? ? p1.printInfo(); // 輸出:Name: Unknown, Age: 0
? ? // 使用帶參構造函數創(chuàng)建對象
? ? Person p2("John", 25);
? ? p2.printInfo(); // 輸出:Name: John, Age: 25
? ? return 0;
}
????????在上面的示例中,Person 類包含了一個默認構造函數和一個帶參構造函數。通過這兩個構造函數,可以選擇使用不同的方式創(chuàng)建 Person 對象,從而靈活地滿足不同的需求。
三、析構函數
??????析構函數概念
????????析構函數:與構造函數功能相反,析構函數不是完成對對象本身的銷毀,局部對象銷毀工作是由編譯器完成的。而對象在銷毀時會自動調用析構函數,完成對象中資源的清理工作。它的主要作用是確保對象使用的資源被正確釋放,防止資源泄漏和內存泄漏的發(fā)生。
?????析構函數的特點
1. 析構函數的名稱與類名相同,但前面有一個波浪線(~)作為前綴。例如,如果類名為MyClass,則對應的析構函數名為~MyClass。
2. 析構函數沒有返回類型,包括void,因為它不返回任何值。
3. 析構函數不接受任何參數,因此不能被重載,每個類只能有一個析構函數。
4. 析構函數不能手動調用,它會在對象生命周期結束時自動被觸發(fā)執(zhí)行。對象銷毀的情況包括對象超出作用域、通過delete釋放了對應的動態(tài)分配內存、容器中的對象被移除等。
5. 當對象的析構函數被調用時,它會自動調用成員對象的析構函數,并按照它們被定義的順序進行銷毀。
6. 如果沒有顯式定義析構函數,編譯器會默認生成一個空的析構函數,即不做任何操作。
????????析構函數通常用于在對象銷毀時執(zhí)行一些必要的清理工作,比如釋放動態(tài)分配的內存、關閉文件句柄、釋放其他類型的資源等。通過析構函數,可以確保對象所使用的資源被正確釋放,避免資源泄漏和內存泄漏的問題。
下面是一個簡單的示例,展示了一個類FileHandler的析構函數的定義和使用
#include <iostream>
#include <fstream>
class FileHandler {
public:
? ? FileHandler(const std::string& filename) {
? ? ? ? file.open(filename);
? ? ? ? if (!file) {
? ? ? ? ? ? std::cout << "Failed to open file " << filename << std::endl;
? ? ? ? }
? ? }
? ? ~FileHandler() {
? ? ? ? if (file.is_open()) {
? ? ? ? ? ? file.close();
? ? ? ? ? ? std::cout << "File closed." << std::endl;
? ? ? ? }
? ? }
? ? void writeToFile(const std::string& data) {
? ? ? ? file << data << std::endl;
? ? }
private:
? ? std::ofstream file;
};
int main() {
? ? FileHandler handler("example.txt");
? ? handler.writeToFile("Hello, world!");
? ? return 0;
}
????????在上面的示例中,F(xiàn)ileHandler類封裝了一個文件句柄,其中構造函數用于打開文件并檢查是否成功打開,而析構函數則負責在對象銷毀時關閉文件。在main函數中,創(chuàng)建了一個FileHandler對象handler并寫入數據,當對象handler超出作用域時,析構函數會被自動調用,關閉文件。
????????通過定義適當的析構函數,可以確保對象的資源在對象銷毀時被正確釋放,從而保證程序運行的安全性和可靠性。也值得注意的是,在使用動態(tài)分配的內存或其他相關資源時,需要顯式定義析構函數,以免造成資源泄漏。
?常見析構函數的幾種類型
根據特定的需求和情況,常見的析構函數可以分為以下四種類型:
????????1. 默認析構函數(Default Destructor):如果沒有顯式定義析構函數,編譯器會隱式地生成一個默認的析構函數。默認析構函數沒有任何實現(xiàn)內容,它的作用僅僅是調用成員對象的析構函數,并按照它們的定義順序進行銷毀。
class MyClass {
? ? // 在這里沒有顯式定義析構函數
? ? // 編譯器會自動生成一個默認析構函數
};
????????2. 虛析構函數(Virtual Destructor):當一個類被繼承時,通常應該考慮使用虛析構函數。虛析構函數在基類中聲明為虛函數,可以確保當通過指向基類的指針刪除一個基類對象時,實際上會調用到派生類的析構函數。這是為了確保析構函數正確釋放所有的資源,包括派生類自己的資源。
class MyBaseClass {
public:
? ? virtual ~MyBaseClass() { // 聲明為虛函數
? ? ? ? // 析構函數的實現(xiàn)
? ? }
};
class MyDerivedClass : public MyBaseClass {
public:
? ? ~MyDerivedClass() {
? ? ? ? // 派生類析構函數的實現(xiàn)
? ? }
};
????????3. 純虛析構函數(Pure Virtual Destructor):純虛析構函數是一個沒有具體實現(xiàn)的虛析構函數。它的存在是為了將基類定義為抽象類,即不能實例化的類。純虛析構函數要求派生類必須提供具體的實現(xiàn)。
class AbstractClass {
public:
? ? virtual ~AbstractClass() = 0; // 純虛析構函數,沒有實現(xiàn)
};
AbstractClass::~AbstractClass() {
? ? // 純虛析構函數的實現(xiàn)
}
class ConcreteClass : public AbstractClass {
public:
? ? ~ConcreteClass() {
? ? ? ? // 派生類的析構函數實現(xiàn)
? ? }
};
????????4. 自定義析構函數(Custom Destructor):自定義析構函數根據類的具體需求定義。它可以用于釋放動態(tài)分配的內存、關閉文件句柄、釋放其他資源等。自定義的析構函數應該根據類的設計在適當的時候進行資源的清理和回收。
class MyClass {
public:
? ? ~MyClass() {
? ? ? ? // 自定義的析構函數實現(xiàn)
? ? ? ? // 釋放資源,關閉文件等
? ? }
};
? ? ? ? 要根據你的需求選擇適當的析構函數類型。大多數情況下,默認析構函數已足夠滿足基本需求,但當涉及到多態(tài)性和繼承時,可能需要使用虛析構函數。對于抽象類,可以使用純虛析構函數。自定義析構函數提供了更靈活的資源清理能力。
四、溫馨提示
????????感謝您對博主文章的關注與支持!在閱讀本篇文章的同時,非常感謝您留下您寶貴的意見和反饋。如果您喜歡這篇文章,可以點贊、評論和分享給您的同學,這將對我提供巨大的鼓勵和支持。另外,博主計劃在未來的更新中持續(xù)探討與本文相關的內容。我會為您帶來更多關于C++以及編程技術問題的深入解析、應用案例和趣味玩法等。請繼續(xù)關注博主的更新,不要錯過任何精彩內容!
????????我將會不斷為大家?guī)砀嗑?、有趣的文章和內容。與這篇文章相關的內容也將陸續(xù)推出,希望你們能夠一直關注我們的動態(tài)。余下的拷貝構造函數、賦值運算符重載、const成員、取地址及const取地址操作符重載詳見下回分解下一篇鏈接:拷貝構造函數、賦值運算符重載、const成員函數
????????再次感謝您的支持和關注。我們期待與您建立更緊密的互動,共同探索C++、算法和編程的奧秘。祝您生活愉快,排便順暢!文章來源:http://www.zghlxwxcb.cn/news/detail-614387.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-614387.html
到了這里,關于【C++入門到精通】C++入門 —— 類和對象(構造函數、析構函數)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!