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

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

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

案例:我们写一个空类,然后创建一个对象,看看这个空对象占用多大空间。

#include<iostream>
#include<string>
using namespace std;
class Person {

};

void test() {
	Person p;
	cout << "size of p is: " << sizeof(p) << endl;
}

int main() {
	test();
	return 0;
}

 运行结果可知:

   空对象大小为1字节,这是因为编译器为了区分空对象占用内存位置,给每个空对象也会分配一个独一无二的内存地址。

 案例:我们写在这个类中添加一个  int 类型的成员变量 m_A。

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

class Person
{
	int m_A;
};

void test01()
{
	Person p;
	cout << "size of p is: " << sizeof(p) << endl;
}

int main()
{
	test01();

	return 0;
}

 运行结果可知:

包含一个int类型成员变量,这个对象的大小是 4字节。

 当我们增加静态成员变量,静态成员函数,非静态成员函数时。

#include<iostream>
#include<string>
using namespace std;
class Person {
	int m_A;
	static int m_B;
	static void func() {};
	void func1() {};
};

void test() {
	Person p;
	cout << "size of p is: " << sizeof(p) << endl;
}

int main() {
	test();
	return 0;
}

 运行结果可知:

      不管是静态成员函数,成员韩式,静态成员变量,均不会增加这个对象所占内存大小。

2:this指针 

问题

Question :  在C++ 中成员变量和成员函数是分开存储的,每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会公用一块代码,那么问题是:这一块代码是如何区分到底哪个对象调用自己的了 ?

Answer:   C++通过提供特殊的对象指针(this指针)来解决上述问题。this指针指向被调用的成员函数所属的对象。 this指针是隐含每一个非静态成员函数的一种指针。 this指针不需要定义,可以直接使用。

this指针用途:

-------》当形参和成员变量同名时,可用this指针来区分。

-------》在类的非静态成员函数中返回对象本身,可使用  return *this 。

案例:现在我们想增加一个成员函数,实现将一个对象的年龄加到另一个对象的年龄上。 

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	Person(int age) {
		// 1:当形参和成员变量同名时,可用 this指针加以区分。
		this->age = age;
	}

	Person& PersonAddPerson(Person& p) {
		this->age += age;
		return *this;
	}

	int age;
};

void test() {
	Person p1(10);
	cout << "p1.age = " << p1.age << endl;
	Person p2(10);
	p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);
	cout << "p2.age = " << p2.age << endl;
}

int main() {
	test();
	return 0;
}

运行结果可知:由于每次执行 PersonAddPerson()函数都能返回当前对象,所以可以实现当前对象p2(age的累加)。 

3:空指针访问成员函数

在C++中空指针也是可以调用成员函数的,但是也需要注意是否使用到 this指针,如果用到 this指针,那么我们就需要添加判断保证代码的健壮性。

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	
	void ShowPerson() {
		cout << "showPerson enter" << endl;
	}

	int age;
};

void test() {
	// Null空指针是可以调用成员函数的
	Person* p = NULL;
	p->ShowPerson();
}

int main() {
	test();
	return 0;
}

如果:成员函数中用到了 this指针,就是不可以的,就需要对this进行判断。

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	
	void ShowPerson() {
		// 事实上属性的前面都是默认添加了 this , 即等同于 this.age 。
		if (this == NULL)
		{
			cout << "当前 person对象为空" << endl;
		}
		else
		{
			cout << age << endl;
		}
	}

	int age;
};

void test() {
	// Null空指针是可以调用成员函数的,但是一旦成员函数使用了 this 就是不可以的
	Person* p = NULL;
	p->ShowPerson();
}

int main() {
	test();
	return 0;
}

4:const修饰成员函数、修饰对象

常函数:

1:  成员函数后加 const,我们称这个函数为  常函数。

2:常函数内不可以修改成员属性。

3:但是成员属性声明时加关键字 mutable ,那么在常函数中依然可以修改。

案例:常函数无法修改普通的成员变量,但是可以修改 mutable修饰的成员变量 。

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	
	/**
		this 指针的本质时一个 指针常量 Person* const this,指针的指向不可以修改,但是指向的值可以修改
		如果想让指针指向的值也不可修改,那么就需要声明为 常函数,在函数的参数列表后添加 const
		这样 this 指针就变成 :  const Person* const this
	
	*/
	void ShowPerson() const {
		// this = NULL; // 不能修改指针的指向
		// this->m_A = 100; //指针this指向的对象的数据也不能修改。
		this->m_B = 100; // mutable修饰的变量时可以修改的。
	}

	int m_A;
	mutable int m_B;
};


int main() {
	
	return 0;
}

常对象:

1:声明对象前 添加 const,那么称该对象为 常对象,常对象无法修改成员变量的值

2:如果成员变量添加了 mutable ,那么常对象可以修改这个成员变量的值

3:常对象只能调用常函数,因为普通函数可能会修改 成员变量的值

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	// 常函数
	void MyFunc()const {}
	// 普通函数
	void MyFunc2() {}
	// 普通变量
	int m_A;
	// mutable 可变变量
	mutable int m_B;
};


int main() {
	const Person person; // 常量对象
	person.MyFunc(); // 常量对象只能调用常量函数
	person.m_A = 100; // 常量对象不能修改普通成员变量
	person.m_B = 100; // 常量对象可以修改 mutable修饰的成员变量
	person.MyFunc2(); // 常量对象也不能调用普通函数
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值