🎩 歡迎來到技術探索的奇幻世界👨?💻
📜 個人主頁:@一倫明悅-CSDN博客
?🏻 作者簡介:?C++軟件開發、Python機器學習愛好者
🗣??互動與支持:💬評論?? ? ?👍🏻點贊?? ? ?📂收藏?? ? 👀關注+
如果文章有所幫助,歡迎留下您寶貴的評論,點贊加收藏支持我,點擊關注,一起進步!
目錄
引言 ? ? ? ? ??? ? ? ??
正文
01-對象模型和this指針簡介? ? ? ? ? ? ? ? ? ?
02-成員變量和成員函數分開存儲? ? ? ? ? ? ? ? ? ?
03-this指針? ? ? ? ? ? ? ? ? ?
04-空指針訪問成員函數 ? ? ? ? ? ? ? ? ?
總結? ? ? ? ? ? ? ? ??
引言 ? ? ? ? ??? ? ? ??
????????在C++中,類是一種用于描述一類對象的數據結構,而對象則是根據類定義創建的實例。類定義了對象的屬性和方法,而對象是類的具體實例化。在C++中,類和對象一起構成了面向對象編程的基礎。
????????在C++中,對象模型是用來描述類和對象之間關系的一種模型。在C++中,每個對象都有自己的一組成員變量和方法,這些成員變量和方法定義在類中。當創建一個對象時,該對象會占用一些內存空間來存儲其成員變量,并且會有一個指向類的指針,這個指針指向該對象所屬的類。
????????this指針是一個隱含的指針,它指向當前對象的地址。在類的成員函數中,可以使用this指針來訪問當前對象的成員變量和方法。this指針的類型是指向當前類的指針。
正文
01-對象模型和this指針簡介? ? ? ? ? ? ? ? ? ?
????????在C++中,對象模型和this指針是面向對象編程的兩個重要概念,它們有助于理解類和對象之間的關系以及在類的成員函數中操作對象的方式。
????????對象模型:
????????對象模型是用來描述類和對象之間關系的一種模型,它包括了對象的內存布局和對象訪問的機制。在C++中,每個對象都有自己的一組成員變量和方法,這些成員變量和方法定義在類中。當創建一個對象時,該對象會占用一些內存空間來存儲其成員變量,并且會有一個指向類的指針,這個指針指向該對象所屬的類。
????????this指針:
????????this指針是一個隱含的指針,它指向當前對象的地址。在類的成員函數中,可以使用this指針來訪問當前對象的成員變量和方法。this指針的類型是指向當前類的指針。通過this指針,可以在成員函數中區分當前對象和其他對象。
????????詳細總結:
?? ? ?(1)對象模型:
? ? ? ? a、對象模型描述了類和對象之間的關系,包括對象的內存布局和訪問機制。
? ? ? ? b、每個對象都有自己的一組成員變量和方法,這些成員定義在類中。
? ? ? ? c、創建對象時,會為其分配內存空間,并有一個指向類的指針。
?? ? ? (2)this指針:
? ? ? ? ?a、this指針是一個隱含的指針,在類的成員函數中自動被創建。
? ? ? ? ?b、this指針指向當前對象的地址,允許在成員函數中訪問當前對象的成員變量和方法。
? ? ? ? ?c、可以用來區分當前對象和其他對象,在處理對象自身的操作時非常有??
????????下面是一個簡單的示例,展示了對象模型和this指針的使用:
????????在上面的示例中,定義了一個名為MyClass的類,該類有一個成員變量value和兩個成員函數setValue和printValue。在setValue函數中,使用this指針來設置當前對象的value值,在printValue函數中,使用this指針來打印當前對象的value值。
????????在main函數中創建了兩個MyClass的對象obj1和obj2,分別調用了setValue和printValue函數來設置和打印對象的value值。
????????通過這個示例,可以看到類和對象之間的關系以及如何使用this指針來操作當前對象的成員變量和方法。
#include <iostream>class MyClass {
public:int value;void setValue(int value) {this->value = value; // 使用this指針設置當前對象的value值}void printValue() {std::cout << "Value: " << this->value << std::endl; // 使用this指針打印當前對象的value值}
};int main() {MyClass obj1;MyClass obj2;obj1.setValue(10);obj2.setValue(20);obj1.printValue(); // 打印obj1的value值obj2.printValue(); // 打印obj2的value值return 0;
}
02-成員變量和成員函數分開存儲? ? ? ? ? ? ? ? ? ?
????????在C++中,成員變量和成員函數是分開存儲的,這是為了提高內存的利用率和程序的執行效率。成員變量存儲在對象的內存空間中,而成員函數則存儲在類的代碼段中,所有對象共享同一份成員函數的代碼。
????????成員變量存儲:
????????成員變量是屬于對象的數據,每個對象都有自己的一份成員變量。當創建一個對象時,系統會為其分配內存空間來存儲成員變量,這些成員變量的大小取決于其類型和數量。每個對象的成員變量存儲在其所占用的內存空間中,不同對象的成員變量是相互獨立的。
????????成員函數存儲:
????????成員函數是屬于類的行為,它們被定義在類的內部,但并不存儲在對象的內存空間中。相反,成員函數的代碼只存儲了一份,它們被存儲在類的代碼段中。所有屬于同一個類的對象共享同一份成員函數的代碼,這樣可以節省內存空間。
????????詳細解釋:
? ? ? ? (1)成員變量存儲:
? ? ? ? a、成員變量是對象的數據,每個對象都有自己的一份成員變量。
? ? ? ? b、當創建對象時,系統會為其分配內存空間來存儲成員變量。
? ? ? ? c、不同對象的成員變量存儲在各自的內存空間中,彼此獨立。
????????(1)成員函數存儲:
? ? ? ? a、成員函數是類的行為,它們被定義在類的內部。
? ? ? ? b、成員函數的代碼存儲在類的代碼段中,而不是存儲在對象的內存空間中。
? ? ? ? c、所有屬于同一個類的對象共享同一份成員函數的代碼,這樣可以節省內存空間。
????????下面是一個簡單的示例,展示了成員變量和成員函數的存儲方式:在這個示例中,可以看到成員變量value存儲在每個對象的內存空間中,而成員函數setValue和getValue的代碼只存儲了一份,它們被所有對象共享。
#include <iostream>class MyClass {
public:int value; // 成員變量void setValue(int val) { // 成員函數value = val; // 訪問成員變量}int getValue() { // 成員函數return value; // 返回成員變量的值}
};int main() {MyClass obj1, obj2; // 創建兩個對象obj1.setValue(10); // 設置對象1的值obj2.setValue(20); // 設置對象2的值std::cout << "Value of obj1: " << obj1.getValue() << std::endl; // 獲取并打印對象1的值std::cout << "Value of obj2: " << obj2.getValue() << std::endl; // 獲取并打印對象2的值return 0;
}
????????下面給出具體的代碼進行分析成員變量和成員函數的使用過程:
????????這個示例展示了C++中成員變量和成員函數分開存儲的情況。在這個示例中,定義了一個名為Person的類,其中包括了非靜態成員變量m_A,靜態成員變量m_B,非靜態成員函數func和靜態成員函數func1。
????????在函數test01中創建了一個Person對象p,并使用sizeof操作符來輸出對象p所占用的字節數。即使對象p是空的,C++編譯器也會分配一個字節的空間來區分空對象的內存位置,確保每個對象都有一個獨一無二的內存地址。
????????在函數test02中再次創建了一個Person對象p,并輸出其占用的字節數,結果應該和test01中的一樣。
????????通過這個示例可以看到,在C++中,即使是空對象也會占用一定的內存空間,同時也展示了成員變量和成員函數分開存儲的情況。
#include <iostream>
using namespace std;// 成員變量和成員函數分開存儲
class Person
{int m_A; // 非靜態成員變量 屬于類對象上static int m_B; // 靜態 不屬于類對象上void func() {} // 非靜態成員函數,也不屬于類對象上static void func1() {} // 靜態成員函數 不屬于類對象上
};void test01()
{Person p;// 空對象占用字節// C++編譯器會給每個空對象也分配一個字節空間,是為了區分空對象所占內存的位置// 每個空對象也應該有一個獨一無二的內存地址cout << "size of p = " << sizeof(p) << endl;
}void test02()
{Person p;cout << "size of p = " << sizeof(p) << endl;
}int main()
{test02();system("pause");return 0;
}
????????示例運行結果如下圖所示:
03-this指針? ? ? ? ? ? ? ? ? ?
????????在C++中,this指針是一個隱含的指針,它指向當前對象的地址。this指針在類的成員函數中自動被創建,并且可以用來訪問當前對象的成員變量和成員函數。通過this指針,可以在成員函數中區分當前對象和其他對象,從而實現對當前對象的操作。
????????詳細解釋:
? ? ? ? (1)this指針的作用:
? ? ? ? a、this指針指向當前對象的地址,允許在成員函數中訪問當前對象的成員變量和成員函數。
? ? ? ? b、當多個對象同時存在時,this指針可以幫助區分當前對象和其他對象,確保操作的是正確的對象。
????????(2)this指針的類型:
? ? ? ? a、this指針的類型是指向當前類的指針,因此在成員函數中可以直接訪問當前類的成員。
? ? ? ? b、在成員函數中,可以通過this->成員變量或this->成員函數的方式來訪問當前對象的成員變量和成員函數。
???????(3)this指針的隱含性:
? ? ? ? a、在類的成員函數中,this指針是隱含的,不需要顯式地聲明或傳遞。
? ? ? ? b、當調用成員函數時,編譯器會自動將當前對象的地址傳遞給this指針。
?????????接下來給出具體代碼分析展示了this指針的使用:詳細解釋代碼如下:
????????這段代碼演示了如何使用this指針在C++中訪問對象的成員變量。在類MyClass
中,定義了一個私有成員變量value
和兩個公有成員函數setValue
和getValue
。在setValue
函數中,使用了this指針來設置當前對象的value
值,而在getValue
函數中,使用this指針來獲取當前對象的value
值。
????????在main
函數中,創建了兩個MyClass
對象obj1
和obj2
,分別設置了它們的value
值為10和20,并通過調用getValue
函數獲取并打印了它們的value
值。
????????這段代碼展示了this指針的隱含性和作用,通過this指針可以在成員函數中準確地訪問當前對象的成員變量,確保操作的是正確的對象。
#include <iostream>class MyClass {
private:int value;public:void setValue(int value) {this->value = value; // 使用this指針設置當前對象的value值}int getValue() {return this->value; // 使用this指針獲取當前對象的value值}
};int main() {MyClass obj1, obj2;obj1.setValue(10); // 設置obj1的value值obj2.setValue(20); // 設置obj2的value值std::cout << "Value of obj1: " << obj1.getValue() << std::endl; // 獲取并打印obj1的value值std::cout << "Value of obj2: " << obj2.getValue() << std::endl; // 獲取并打印obj2的value值return 0;
}
????????下面給出具體的代碼進行分析this指針的使用過程:這個示例展示了在C++中使用this指針解決名稱沖突和返回對象本身的情況。在這個示例中,定義了一個名為Person的類,其中包括了一個構造函數和成員函數PersonAddAge,以及一個整型成員變量age。
????????解決名稱沖突:在函數test01中,創建了一個Person對象p1并初始化其年齡為18,在構造函數中使用了this指針來設置對象的年齡。通過this指針,可以準確地訪問當前對象的成員變量,避免與函數參數或局部變量發生沖突。
????????返回對象本身:在函數test02中,創建了兩個Person對象p1和p2,并多次調用PersonAddAge函數來累加p1對象的年齡到p2對象。在PersonAddAge函數中,使用了this指針來訪問當前對象的成員變量,同時返回值類型為Person&,表示返回的是當前對象的引用,實現了對同一個對象連續調用多次函數的鏈式操作。
????????在test02函數中,通過鏈式調用的方式,三次調用PersonAddAge函數將p1對象的年齡累加到p2對象中,最終輸出了p2對象的年齡。
????????值得注意的是,在鏈式調用時需要確保PersonAddAge函數返回的是當前對象的引用(*this),這樣才能保證連續調用的有效性。
????????通過這個示例,展示了this指針在成員函數中的作用,以及如何使用this指針解決名稱沖突和實現返回對象本身的功能。
#include <iostream>
using namespace std;class Person
{
public:Person(int age){// this指針指向的是被調用的成員函數所屬的對象this->age = age; }Person& PersonAddAge(Person &p){this->age += p.age;return *this; // this指向的是p2的指針,而*this指向的就是p2這個對象本體}int age; // 這里一般會定義的時候,盡量與構造函數傳入的參數分辨清楚,或者在構造函數里加入this
};// 1、解決名稱沖突
void test01()
{Person p1(18);cout << "p1的年齡: " << p1.age << endl;}// 2、返回對象本身用 return *this 且返回值類型,為該對象的類,加引用方式返回void test02()
{Person p1(10);Person p2(10);// p2.PersonAddAge(p1);// 若想使用鏈式的方法多次相加,需要進行成員函數更改/* 具體方面如下1、當成員函數PersonAddAge()執行一次之后,返回值是void2、返回值是void,當然不能再對該成員函數進行調用,因此,返回值必須是p2才可以3、而這里說了返回對象本身用 return *this 且返回值類型,為該對象的類,加引用方式返回4、因此改成Person &PersonAddAge(Person &p){this->age += p.age;return *this;}*/p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);cout << "p2的年齡為:" <<p2.age<< endl;}int main()
{//test01();test02();system("pause");return 0;
}
????????示例運行結果如下圖所示:
04-空指針訪問成員函數 ? ? ? ? ? ? ? ? ?
????????在C++中,空指針訪問成員函數是指在一個空指針上調用成員函數的情況。空指針是指未指向任何有效對象的指針,即其存儲的地址為0或nullptr。當嘗試在空指針上調用成員函數時,由于沒有有效對象來執行函數,可能會導致程序崩潰或未定義的行為。
????????空指針的含義:
????????空指針是指未指向任何有效對象的指針,通常表示為nullptr(在C++11及以后版本)或0(在較早的C++版本中)。
????????空指針不指向任何有效的內存地址,因此在其上調用成員函數將導致未定義的行為。
????????空指針訪問成員函數的影響:
????????當在空指針上調用成員函數時,由于沒有有效的對象來執行函數體,程序可能會發生崩潰或產生未定義的行為。
????????這是因為成員函數通常需要訪問對象的成員變量或其他成員函數,而空指針并不指向任何對象,因此無法執行成員函數的操作。
????????下面是一個簡單的示例,演示了空指針訪問成員函數的情況:
????????在這個示例中,創建了一個名為MyClass的類,其中包含一個成員函數printMessage用于打印消息。在main函數中,創建了一個空指針ptr,并嘗試在其上調用printMessage成員函數。
????????然而,由于ptr是一個空指針,它并不指向任何有效的對象,因此在調用printMessage函數時將導致未定義的行為,可能會導致程序崩潰或產生其他意外結果。
#include <iostream>class MyClass {
public:void printMessage() {std::cout << "Hello, world!" << std::endl;}
};int main() {MyClass* ptr = nullptr; // 創建一個空指針ptr->printMessage(); // 嘗試在空指針上調用成員函數return 0;
}
????????解決方法:
????????為了避免空指針訪問成員函數導致的問題,可以在調用成員函數之前進行空指針的有效性檢查,確保指針不為空才進行調用。例如:通過這樣的有效性檢查,可以避免空指針訪問成員函數帶來的潛在問題,增加程序的健壯性和穩定性。
if (ptr != nullptr) {ptr->printMessage();
} else {// 處理空指針的情況,如輸出錯誤信息或進行其他操作std::cerr << "Error: Pointer is null." << std::endl;
}
下面給出具體代嗎分析應用:
#include <iostream>
using namespace std;// 空指針調用成員函數class Person
{
public:void showClassName(){cout << "this is Person class" << endl;}void showPersonAge(){// 這里傳入的指針為空,將會報錯if (this == NULL) // 這個判斷可以防止傳入空指針出錯{return;}cout << "年齡age = " << m_Age << endl;}int m_Age;
};void test01()
{Person *p = NULL;p->showClassName();// 這里出錯,主要原因如下/* 1、cout << "年齡age = " << m_Age << endl;這句代碼里m_Age這里默認是this->m_Age2、但是這里定義的對象只是一個空指針,對于一個空指針來說,訪問里面的成員是不可能的*/p->showPersonAge();}int main()
{test01();//test02();system("pause");return 0;
}
?????????示例運行結果如下圖所示:
總結? ? ? ? ? ? ? ? ??
????????在C++中,對象模型和this指針是面向對象編程的兩個重要概念,它們有助于理解類和對象之間的關系以及在類的成員函數中操作對象的方式。
????????在C++中,對象模型是用來描述類和對象之間關系的一種模型。在C++中,每個對象都有自己的一組成員變量和方法,這些成員變量和方法定義在類中。當創建一個對象時,該對象會占用一些內存空間來存儲其成員變量,并且會有一個指向類的指針,這個指針指向該對象所屬的類。
????????this指針是一個隱含的指針,它指向當前對象的地址。在類的成員函數中,可以使用this指針來訪問當前對象的成員變量和方法。this指針的類型是指向當前類的指針。
?