C++对象模型与this指针

 

目录

一、成员变量与成员函数分开存储

二、this指针

性质:

作用:

三、空指针访问成员函数

C++中空指针也可以调用成员函数,不过要注意是否用到this指针

如果遇到this指针,加上判断,防止代码出错

四、const修饰成员函数

常函数:

本质:person * const this;

本质:const person *const this;

常对象:


一、成员变量与成员函数分开存储

1、在C++中,类内的成员变量和成员函数分开存储

首先,对于一个空对象,占用内存空间为1

class person
{

};

void test01()
{
	person p;
	cout << sizeof(p) << endl;
}

C++对象模型与this指针_第1张图片

 因为C++编译器给每个空对象分配1个字节空间,防止不同空对象占用同一块内存空间,便于区分


2、只有非静态成员变量属于类的对象上

 在person类中加入一个非静态成员变量

class person
{
	int m_a; // 非静态成员变量,属于类的对象上
};

void test02()
{
	person p;
	cout << sizeof(p) << endl;
}

C++对象模型与this指针_第2张图片

 再加上静态成员变量

C++对象模型与this指针_第3张图片

再加上非静态成员函数

C++对象模型与this指针_第4张图片

最后加上静态成员函数 

 C++对象模型与this指针_第5张图片

 总结:只有非静态成员变量才属于类的对象上


二、this指针

概念:上一节中我们知道成员变量与成员函数分开存储,每一个非静态成员函数只会产生一份函数实例,也就是多个同类型的对象共用一块代码,而如何区分究竟是哪个对象调用自己,用到this指针

this指针指向被调用的成员函数所属的对象

性质:

①this指针是隐含在每一个非静态成员函数内的一种指针

②this指针不需要定义,可以直接使用

作用:

①当形参与成员变量同名时,可用this指针加以区分

举例说明:我们先创建类person和测试函数test01,在类内创建属性m_age,函数person,形参age

class person
{
public:
	person(int age)
	{
		m_age = age;
	}
	int m_age;
};
void test01()
{
	person p(20);
	cout << p.m_age << endl;
}

此时可正常输出

但是,如果我们将属性m_age改为age得到这个

class person
{
public:
	person(int age)
	{
		age = age;
	}
	int age;
};
void test01()
{
	person p(20);
	cout << p.age << endl;
}

C++对象模型与this指针_第6张图片

同颜色的即为同一个age,无法正常输出

在此基础上,我们在函数内加上this指针

class person
{
public:
	person(int age)
	{
		this->age = age; // 加上this->
	}
	int age;
};

C++对象模型与this指针_第7张图片

 可以发现3个age是同源的。此时,this就代表p,this->age == p.age;

C++对象模型与this指针_第8张图片


②在类的非静态成员函数中返回对象本身,可以用return *this;

class person
{
public:
	person(int age)
	{
		this->age = age;
	}
	void personAdd(person& p) // 函数本体age加上参数P的age
	{
		this->age += p.age;
	}
	int age;
};
void test02()
{
	person p1(10);
	cout << p1.age << endl;
	person p2(10);
	cout << p2.age << endl;
}

C++对象模型与this指针_第9张图片

 而如果我们想要多次加和

void test02()
{
	p2.personAdd(p1);
	cout << p2.age << endl;

	p2.personAdd(p1).personAdd(p1).personAdd(p1); // 想要多次加和
	cout << p2.age << endl;
}

C++对象模型与this指针_第10张图片

要先修改函数体返回值

person& personAdd(person& p) // 而且要引用
	{
		this->age += p.age;
		return *this; // 返回对象本身
	}

C++对象模型与this指针_第11张图片

而如果函数体返回值不使用引用&,则无法修改值, 

C++对象模型与this指针_第12张图片

 因为这样修改完第一次p2后,返回的是另一个变量,并且后面第2次开始修改的都是另一个变量,再另一个变量


三、空指针访问成员函数

C++中空指针也可以调用成员函数,不过要注意是否用到this指针

如果遇到this指针,加上判断,防止代码出错

class person
{
public:
	void show_name()
	{
		cout << "Joyce" << endl;
	}
	void show_age()
	{
		cout << this->m_age << endl;
	}

	int m_age;

};
void test01()
{
	person* p = NULL;
	p->show_age(); // 非法访问
	p->show_name();
}

对于这段代码,指针p为NULL,调用show_name函数时可以正常输出,因为她只是简单的打印特定的内容,而调用show_age函数时将报错,因为函数内this->m_age;调用了this指针的m_age,而this指针为NULL,造成非法访问

因此,我们在函数内部加上判断

void show_age()
	{
		if (this == NULL)
		{
			return;
		}
		cout << this->m_age << endl;
	}

以此便可以防止代码为NULL时出错


四、const修饰成员函数

常函数:

①成员函数后加const称该函数为成员函数

②常函数不可以修改成员属性

③成员属性声明时加关键字mutable,在常函数中仍然能修改


接下来创建person类与函数show_name;

class person
{
public:
	void show_name()
	{
		this->m_a = 100; // 非 常对象,可修改
		this = NULL;// this指针的指向不可修改
	}
	int m_a;
};

C++对象模型与this指针_第13张图片

 因为this指针本质是一个指针常量,所以其指向(地址)不可修改,但其指向的值可以修改

本质:person * const this;


不过,如果在函数加上const,则地址与值都不可修改

本质:const person *const this;

C++对象模型与this指针_第14张图片

 不过,如果在常函数中的属性的声明前加上mutable,则可以修改

class person
{
public:
	void show_name() const // 这里有const
	{
		this->m_a = 100; //可修改
	}
	mutable int m_a; // 加上const
};

常对象:

①声明对象前加const称该对象为常对象

②常对象只能调用常函数


class person
{
public:
	void show_name() const
	{
		this->m_a = 100; 
	}
	mutable int m_a;
	int m_b;
};
void test02()
{
	person p;
	p.m_b = 20; 
}

此时test02内可以修改m_b;接下来在p前加上const使其变成常对象

void test02()
{
	const person p;
	p.m_b = 20; // 不可修改
	p.m_a = 20; // 可修改
}

则m_b不可修改,而m_a由于前面加了mutable,可以修改

C++对象模型与this指针_第15张图片


同时,在person类中我们再创建一个普通函数func,尝试在test函数中调用刚才的常函数和普通函数

class person
{
public:
	void show_name() const // 常函数
	{
		this->m_a = 100; 
	}
	void func() // 普通函数
	{
		;
	}
	mutable int m_a;
	int m_b;
};

void test02()
{
    const person p; // 创建常对象
	p.show_name(); // 常函数
	p.func(); // 普通函数
}

C++对象模型与this指针_第16张图片

 无法调用,因为常对象只能调用常函数(因为普通函数可以修改属性)

你可能感兴趣的:(c++)