c++对象模型和this指针

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

在c++中,类内的成员变量和成员函数是分开存储

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

空对象占用多少内存空间呢?

# include 
using namespace std;

class Person
{
	
};

void test01()
{
	Person p;
	//空对象占用内存空间为:1 
	//c++编译器 会给每个空对象分配一个字节空间
	//是为了区分内存空间的位置  
	cout << "size of p = " << sizeof(p) << endl;
}

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

c++对象模型和this指针_第1张图片

    空对象占用内存空间为:1 
    c++编译器 会给每个空对象分配一个字节空间
    是为了区分内存空间的位置   每个空对象也应该有一个独一无二的内存地址

 非静态成员变量 属于类的对象上 

# include 
using namespace std;

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

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

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

c++对象模型和this指针_第2张图片

静态成员变量 不属于类的对象上 

# include 
using namespace std;

class Person
{
	int m_A;//非静态成员变量 属于类的对象上 
	
	static int m_B;//静态成员变量 不属于类的对象上  
};

int Person::m_B = 5;//初始化静态变量  

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

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

 此时 运行结果依旧是4

c++对象模型和this指针_第3张图片

非静态和静态成员函数 都不属于类的对象上

# include 
using namespace std;

class Person
{
	int m_A;//非静态成员变量 属于类的对象上 
	
	static int m_B;//静态成员变量 不属于类的对象上
	
	void func() {};//非静态成员函数 不属于类的对象上
	
	static void func2() {};//静态成员函数 不属于类的对象上   
};

int Person::m_B = 5;//初始化静态变量  

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

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

c++对象模型和this指针_第4张图片

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

 this指针概念

我们知道在c++中成员变量和成员函数是分开存储的 

每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码

那么问题就是:这一块代码是如何区分哪个对象调用自己的呢?

c++通过提供特殊的对象指针,this指针,解决上述问题。

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

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

this指针不需要定义 直接使用即可

this指针的用途

1、当形参和成员变量同名时,可用this指针来区分(解决名称冲突) 

# include 
using namespace std;

class Person
{
	public:
		int age;
	Person(int age)//形参与成员变量同名 
	{
		age = age;
	}	
}; 

void test01()
{
	Person p1(18);
	cout << "p1的年龄为:" << p1.age << endl; 
 } 

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

 命名冲突时 无法进行正常的赋值操作

c++对象模型和this指针_第5张图片

 用this指针解决

# include 
using namespace std;

class Person
{
	public:
		int age;
	Person(int age)//形参与成员变量同名 
	{   //this指针指向的是 被调用的成员函数 所属的对象 
		//此时this指向p1 
		this->age = age;
	}	
}; 

void test01()
{
	Person p1(18);
	cout << "p1的年龄为:" << p1.age << endl; 
 } 

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

c++对象模型和this指针_第6张图片

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

# include 
using namespace std;

class Person
{
	public:
		int age;
	Person(int age)//形参与成员变量同名 
	{   //this指针指向的是 被调用的成员函数 所属的对象 
		//此时this指向p1 
		this->age = age;
	}	
	
	Person & PersonAddAge(Person & p)//注意返回值的类型  
	{
		this->age += p.age;	
		return *this;//this指向p2的指针 而*this指向的就是p2这个对象的本体  
	}
}; 

void test01()
{
	Person p1(18);
	cout << "p1的年龄为:" << p1.age << endl; 
} 

void test02()
{
	Person p1(10);
	Person p2(20);
	
	p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
	cout << "p2的年龄为:" << p2.age << endl; 
}

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

c++对象模型和this指针_第7张图片

 如果把函数的返回值类型改变(去掉&)

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

运行结果

c++对象模型和this指针_第8张图片

 因为如果返回的类型不是引用类型 而是类的话 这个时候就会调用复制构造函数 而调用的是临时变量的复制构造函数 因此p2的年龄只被改变了一次 即30

 c++对象模型和this指针_第9张图片

 p` 和p``和p```临时变量

空指针访问成员函数

c++中空指针也是可以调用成员函数的 但是也要注意有没有用到this指针(用到this指针时就不行)

如果用到this指针,需要加以判断保证代码的健壮性 

# include 
using namespace std;

class Person
{
	public:
		int m_Age;
		
		void showClassName()
		{
			cout << "this is Person class" << endl;	
		}	
		
		void showPersonAge()
		{				
			if ( this == NULL )//保证代码的健壮性
				return;      //m_Age等价于this->m_Age  
			cout << "age = " << m_Age << endl;//传入的指针为空  
		}
};

void test01()
{
	Person * p = NULL;
	p->showClassName();
	p->showPersonAge(); 
}

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

const修饰成员函数

常函数:

成员函数后加const后我们称这个函数为常函数

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

成员属性声明时加关键字mutable后,在常函数中依然可以修改

 


class Person
{
	public:
		//this指针的本质 是指针常量 指针指向是不可以修改的 
		//const Person * const this;
		//在成员函数后面加const,修饰的是this指针 让指针指向的值也不能修改  
		void showPerson() const
		{
			this->m_A = 100;//OK
			//this->m_A = 100;//不可以改变指针指向的值 
			//this = NULL;//this指针不可以修改指针的指向  
		}
		
		int m_A;
		mutable int m_B;//特殊变量 即使在常函数中 也可以修改这个值 		
}; 

常对象:

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

常对象只能调用常函数

 

void test()
{
	const Person p;//在对象前加const 变为常对象
	//p.m_A = 100;//不可以修改
	p.m_B = 100;//ok m_B是特殊值 在常对象下也可以修改 
	
	//常对象只能调用常函数
	p.showPerson();//ok
//	p.func();//no  func为类的普通成员函数(非常函数) 
//因为普通成员函数可以修改属性 
} 

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