天天看點

C++核心程式設計---4.3 類和對象-對象模型和 this 指針【P114~P117】4.3 類和對象-對象模型和 this 指針

C++核心程式設計---4.3 類和對象-對象模型和 this 指針【P114~P117】

  • 4.3 類和對象-對象模型和 this 指針
    • 4.3.1 成員變量和成員函數分開存儲
    • 4.3.2 this 指針的用途
    • 4.3.3 空指針通路成員函數
    • 4.3.4 const 修飾成員函數

4.3 類和對象-對象模型和 this 指針

4.3.1 成員變量和成員函數分開存儲

在C++中,類内的成員變量和成員函數分開存儲

隻有非靜态成員變量才屬于類的對象上

#include<iostream>
#include<string>
using namespace std;

//成員變量和成員函數是分開存儲的

class Person
{
	int m_A;//非靜态成員變量,屬于類的對象上
	static int m_B;//靜态成員變量(特點是要類内聲明,類外初始化),不屬于類的對象上
	void func(){};//非靜态成員函數	不屬于類的對象上
	static void func02() {};//非靜态成員函數	不屬于類的對象上
};

int Person::m_B = 0;//類外初始化

void test01()//主要了解空對象占多大記憶體
{
	Person p;
	//空對象占用記憶體空間為 1 位元組
	//C++編譯器會給每個空對象也配置設定一個位元組空間,是為了區分空對象占記憶體的位置
	//每個空對象也應該有一個獨一無二的記憶體位址
	cout << "size of p = " << sizeof(p) << endl;
}

void test02()
{
	Person p;
	cout << "size of p = " << sizeof(p) << endl;
}

int main()
{
	//test01();
	test02();

	system("pause");
	return 0;
}
           

4.3.2 this 指針的用途

通過上一節内容知道C++中成員變量和成員函數是分開存儲的

每一個非靜态成員函數隻會誕生一份函數執行個體,也就是說多個同類型的對象會共用一塊代碼

那麼,這一塊代碼是如何區分是哪個對象調用自己的呢?

C++是通過提供特殊的對象指針,this 指針,解決上述問題:this 指針指向被調用的成員函數所屬的對象(哪個對象調用了這個共用的成員函數,this 指針就會指向誰)

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

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

this 指針的用途:

  • 當形參和成員變量同名時,可用 this 指針來區分
  • 在類的非靜态成員函數中傳回對象本身,可使用 return *this ( * :解引用操作,傳回這個對象 )
#include<iostream>
#include<string>
using namespace std;

class	Person
{
public:
	Person(int age)//形參名稱
	{
		//this指針指向的是被調用的成員函數所屬的對象
		this->age = age;
	}

	Person & PersonAddAge(Person &p)//如果去掉引用符号,就會傳回值,建立了新的對象;但如果加上引用符号,傳回的一直是本體
	{
		this->age += p.age;
		//this 指向p2的指針,而*this指向的就是p2這個對象本體
		return *this;
	}

	int age;//成員屬性
};


//1、解決形參和成員變量名稱沖突的問題
void test01()
{
	Person p1(18);
	cout << "p1的年齡為: " << p1.age << endl;
}

//2、傳回對象本身用*this
void test02()
{
	Person p1(10);
	Person p2(10);
	//鍊式程式設計思想
	p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
	cout << "p2的年齡是: " << p2.age << endl;
}

int main()
{
	test01();
	test02();

	system("pause");
	return 0;
}
           

4.3.3 空指針通路成員函數

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

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

#include<iostream>
#include<string>
using namespace std;

//空指針調用成員函數

class Person
{
public:

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

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

void test01()
{
	Person *p = NULL;
	p->showClassName();
	p->showPersonAge();//這一行報錯,因為空指針沒有指向實體對象,再調用這個不存在的對象的成員屬性就更荒謬了
}

int main()
{
	test01();

	system("pause");
	return 0;
}
           

4.3.4 const 修飾成員函數

常函數

  • 成員函數後加 const 後我們稱這個函數為常函數
  • 常函數内不可以修改成員屬性
  • 成員屬性聲明時加關鍵字 mutable 後,在常函數中依然可以修改

常對象

  • 聲明對象前加 const 稱該對象為常對象
  • 常對象隻能調用常函數
#include<iostream>
#include<string>
using namespace std;

//1、常函數
class Person
{
public:

	//this 指針的本質 是指針常量  指針的指向是不可以修改的
	//Person * const this;   this 指針的指向不可以修改
	//const Person * const this;    這時 this 指針指向的值也不可以修改了

	void showPersonName()const //上邊一行注釋的等效做法,這時成員函數就是常函數了,常函數内就不可以再修改成員屬性的值了
	{
		//this->m_A = 100;
		this->m_B = 100;
	}

	void func()
	{
	
	}
	int m_A;
	mutable int m_B;//特殊變量,即使在常函數中也可以修改這個值
};

void test01()
{
	Person p;
	p.showPersonName();
}

//2、常對象

void test02()
{
	const Person p;//在對象前加 const ,變為常對象
	p.m_A = 100;//報錯,常對象的值不可以修改
	p.m_B = 100;

    //常對象隻能調用常函數
	p.showPersonName();//常對象調用常函數,沒毛病
	p.func();//報錯,常對象調用的不是常函數
}

int main()
{
	test01();
	test02();

	system("pause");
	return 0;
}
           

繼續閱讀