天天看點

【C++筆記】對象模型和this指針

一、成員變量和成員函數分開存儲

C++中,類内的成員變量和成員函數分開存儲,隻有非靜态成員變量才屬于類的對象

  1. 空對象也會占用記憶體

    C++編譯器會給每個空對象也配置設定一個位元組空間,是為了标志此對象占記憶體的位置。每個空對象也應該有一個獨一無二的記憶體位址

    class Person{};
               
    cout << "size of p = " << sizeof(p) << endl;
               
    空對象占用1個位元組記憶體
  2. 隻有類的非靜态成員變量,屬于類的對象
    class Person{
    	int m_A;
    };
               
    cout << "size of p = " << sizeof(p) << endl;
               
    隻含一個int非靜态成員變量的對象占用4個位元組記憶體
  3. 類的靜态成員變量,不屬于類的對象
    class Person{
    	int m_A;
    	static int m_B;
    };
    int Person::m_B = 100;
               
    cout << "size of p = " << sizeof(p) << endl;
               
    對象還是占用4個位元組記憶體
  4. 成員變量和成員函數是分開存儲的
    class Person{
    	int m_A;
    	static int m_B;
    	void func(){}
    };
               
    cout << "size of p = " << sizeof(p) << endl;
               
    對象還是占用4個位元組記憶體

二、this指針

有上述可知,C++中成員變量和成員函數是分開存儲的。

每一個非靜态成員函數隻會産生一份函數執行個體,也就是多個同類型的對象會共用一塊代碼,而代碼如何區分哪個對象調用自己。

這裡就用到了this指針,this指針指向被調用的成員函數所屬的對象

this指針是隐含每一個非靜态成員函數内的一種指針

this指針不需要定義,直接使用即可

this指針的用途:

  • 形參和成員變量同名時,可以用this指針來區分
  • 在類的非靜态成員函數中傳回對象本身,可使用return *this
#include<iostream>
using namespace std;

class Person{
public:
	Person(int money){
		//this指針指向被調用的成員函數所屬的對象
		this->money = money;	//如果不加this,則指派兩側會認為是同一個money
	}

	Person& PersonAddMoney(Person &p){
		this->money += p.money;	//将傳入的p對象的money加到此對象上
		return *this;	//this是指向對象的指針,*this就是指向對象本體
	}

	int money;
};

void test01(){
	Person p1(18);
	cout << "p1的财産為:" << p1.money << endl;
}

void test02(){
	Person p1(10);
	Person p2(10);
	p2.PersonAddMoney(p1).PersonAddMoney(p1).PersonAddMoney(p1);//鍊式程式設計
	cout << "p2的财産為:" << p2.money << endl;

}

int main(){

	//test01();
	test02();

	system("pause");
	return 0;
}
           

三、空指針通路成員函數

C++中空指針也可以調用成員函數,但是也要注意有沒有用到this指針

如果用到this指針,需要加判斷保證代碼的健壯性。

#include <iostream>
using namespace std;

class Person{
public:

	void showClassName(){
		cout << "This is Person class." << endl;
	}

	void showPersonAge(){
		if(this == NULL){
			return ;
		}
		cout << "age = " << this->m_Age << endl;	//報錯原因是傳入的指針為空
	}
	
	int m_Age;
};

void test01(){
	Person * p = NULL;
	p->showClassName();	//空指針也可以正常執行
	p->showPersonAge();	//如果不加if語句會報錯
}

int main(){

	test01();

	system("pause");
	return 0;
}
           

四、const修飾成員函數

常函數:

  • 成員函數後加const後我們稱為這個函數為常函數
    void showPerson() const {}
               
  • 常函數不可以修改成員屬性

    常函數也存在this指針,而this指針的本質是指針常量,指針的指向是不可修改的。

    在成員函數後面加this,修飾的是this指向,讓指針指向的值也不可以修改。

    class Person{
    public:
    	void showPerson() const {
    		this->m_A = 100;	//報錯
    	}
    
    	int m_A;
    }
               
  • 成員屬性聲明時加關鍵字mutable,在常函數中依然可以修改
    mutable int m_B;
               
    建立了一個特殊的變量,即使在常函數中也可以修改,常對象也可以修改

常對象

  • 對象前加const,建立的是常對象
    const Person p;
               
  • 常對象無法修改成員變量,值可以修改加mutable的變量
  • 常對象隻能調用常函數,不能調用普通成員函數,因為普通成員函數可以修改屬性

    參考:黑馬程式員匠心之作|C++教程從0到1入門程式設計,學習程式設計不再難

    連結:https://www.bilibili.com/video/BV1et411b73Z

繼續閱讀