C++类和对象(三):C++对象模型和this指针


1 成员变量和成员函数分开存储

C++中,类的成员变量和成员函数分开存储。只有非静态成员变量属于类的对象,占用对象的内存空间

注1:非静态成员函数静态成员(包括静态成员变量与静态成员函数)均不属于类的对象,不占用对象的内存空间
注2:非静态成员函数并非某个对象独有,内存中仅存在一份数据(一份函数实例)。不同对象的某个非静态成员函数共享同一个函数实例,即多个同类型的对象会共用一块代码。
注3:空对象占用内存空间大小为1字节。每个对象均具有独一无二的内存地址,C++编译器为区分不同的空对象,会为每个空对象分配1个字节的内存空间。

示例

#include <iostream>
using namespace std;

//空类
class Empty {
    
    

};

class Object {
    
    
	//非静态成员变量:属于类的对象,占用对象的内存空间
	int var;
	
	//静态成员变量:不属于类的对象,不占用对象的内存空间
	static int s_var;
	
	//非静态成员函数:不属于类的对象,不占用对象的内存空间
	void func() {
    
    }
	
	//静态成员函数:不属于类的对象,不占用对象的内存空间
	static void s_func() {
    
    }
};

int main() {
    
    
	Empty e;
	cout << "空对象占用的内存大小:" << sizeof(e) << endl;	//1

	Object o;
	cout << "非空对象占用的内存大小:" << sizeof(o) << endl;	//4

	return 0;
}

2 this指针

C++提供特殊的对象指针this指针,用于区分共享的同一块代码(如非静态成员函数)由某个对象调用。

this指针的特点
(1)this指针指向被调用的成员函数所属的对象(某个对象调用成员函数,this指针即指向该对象)。
(2)this指针是隐含在每个非静态成员函数内的一种指针。
(3)this指针无需定义,可直接使用

this指针的本质:this指针本质是指针常量,等价于数据类型* const this,即指针的指向不可修改,但指向的值可以修改

this指针的作用
(1)当成员变量函数形参同名时,可使用this指针区分,解决名称冲突。
(2)在类的非静态成员函数中,*this可表示对象本身return *this;返回当前对象
①当函数以值类型返回,即返回类型为类类型,会调用拷贝构造函数创建并返回当前对象的拷贝
②当函数以引用类型返回,即返回类型为类类型 &,会返回当前对象本身

注1:this是指向对象的指针,可通过解引用操作*this获取对象。
注2:this->成员属性等价于(*this).成员属性

总结:
①函数中创建并返回临时对象时,函数返回类型应为值类型类类型,而不能为引用类型
原因:临时变量在函数调用完毕后释放,若返回类型为引用类型即为同一个对象,访问已被释放的内存为非法操作;应返回值类型,创建临时对象的拷贝并返回。
②为保证链式编程风格或调用的对象全局唯一时,函数返回类型应为引用类型类类型 &,而不能为值类型
原因:若返回类型为值类型,会创建当前对象的拷贝并返回,调用与返回的对象不是同一个对象;应返回引用类型,保证调用与返回同一个对象

示例

#include <iostream>
using namespace std;

class Account {
    
    
public:
	int balance;
	
	/* 使用this指针区分成员变量与函数形参同名的冲突 */
	Account(int balance) {
    
    
		//this->成员属性 等价于 (*this).成员属性
		//(*this).balance = balance;
		this->balance = balance;
	}

	//以【引用类型】返回
	Account& sum1(Account a) {
    
    
		this->balance += a.balance;
		return *this;	//返回当前对象
	}

	//以【值类型】返回
	Account sum2(Account a) {
    
    
		this->balance += a.balance;
		return *this;	//返回当前对象的拷贝
	}
};

int main() {
    
    
	Account a(10);
	Account b(0);
	Account c(0);

	/* 链式编程 */
	//以【引用类型】返回————返回当前对象本身
	b.sum1(a).sum1(a).sum1(a);
	cout << b.balance << endl;	//30

	//以【值类型】返回————返回当前对象的拷贝
	c.sum2(a).sum2(a).sum2(a);
	cout << c.balance << endl;	//10

	return 0;
}

3 空指针访问成员函数

C++中,空指针可调用成员函数
若成员函数中访问成员变量时(即隐含地使用this指针时),需进行判空处理以保证代码的健壮性。

//判空代码
if(this == NULL){
    
    
	return;
}

示例:空指针访问成员函数

//空指针访问成员函数
#include <iostream>
using namespace std;

class Object {
    
    
public:
	int field;

	//成员函数中未访问成员变量(未使用this指针)
	void print() {
    
    
		cout << "Hello" << endl;
	}

	//成员函数中访问成员变量(使用this指针)
	void func() {
    
    
		/* 判空处理 */
		if (this == NULL) {
    
    
			return;
		}
		cout << field << endl;	//访问成员变量时,等价于 this->成员变量
	}
};

int main() {
    
    
	//空指针
	Object* obj = NULL;

	/* 空指针访问成员函数 */
	obj->print();	//程序正常:Hello
	obj->func();	//未判空处理时,程序崩溃

	system("pause");
	return 0;
}

4 const修饰成员函数(常函数与常对象)

4.1 常函数

常函数:成员函数的形参列表后,使用关键字const修饰。
语法返回类型 函数名() const {...}
特点:常函数内,成员变量不可修改
本质:成员函数后使用关键字const修饰,本质相当于修饰this指针指针常量),则this指针指向的值亦不可修改。

注1:this指针本质指针常量,等价于数据类型* const this,即指针的指向不可修改,但指向的值可以修改
注2:
普通成员函数中,成员变量等价于this->成员变量this等价于数据类型* const this
常函数中,this等价于const 数据类型* const this,则this->成员变量指针的指向与指向的值均不可修改。若修改常函数中的成员变量的值,则编译器报错:表达式必须是可修改的左值
注3:当成员属性声明时,若使用关键字mutable修饰,则在常函数中仍然可以修改。


4.2 常对象

常对象:对象在声明时,使用关键字const修饰。
特点
(1)常对象的成员变量不可修改
(2)常对象只能调用常函数

注1:当成员属性声明时,若使用关键字mutable修饰,则在常对象中仍然可以修改。
注2:常对象不可调用普通成员函数,因为普通成员函数中成员属性可修改,与常对象的成员变量不可修改相斥。否则,编译器报错:对象含有与成员函数XXX::func()不兼容的类型限定符

示例

#include <iostream>
using namespace std;

class Object {
    
    
public:
	int field;
	mutable int var;

	/* 常函数:成员变量不可修改 */
	//常函数中的const,本质相当于修饰this指针(指针常量),则this指针的指向与指向的值均不可修改
	void func() const {
    
    
		//field = 1;	//报错:表达式必须是可修改的左值
		var = 2;		//使用mutable声明的成员变量,在常函数中仍可修改
	}

	/* 普通成员函数 */
	void func2() {
    
    
		field = 1;
		var = 2;
	}
};

int main() {
    
    
	/* 常对象:常对象的成员变量不可修改;常对象只能调用常函数 */
	const Object obj;

	/* 常对象的成员变量不可修改 */
	//obj.field = 1;	//报错:表达式必须是可修改的左值
	obj.var = 2;		//使用mutable声明的成员变量,在常对象中仍可修改

	/* 常对象只能调用常函数 */
	obj.func();
	//obj.func2();	//报错:对象含有与成员函数Object::func2()不兼容的类型限定符;对象类型是const Object

	return 0;
}

猜你喜欢

转载自blog.csdn.net/newson92/article/details/113641404