C++学习笔记(十三)

2023-12-14 23:50:59

一、C++对象模型和this指针

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

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

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

#include <iostream>

using namespace std;

class a1
{

};

class a2
{
	int a;
};

class a3
{
	int a;
	static int b;
};

class a4
{
	int a;
	void func(){}
};

class a5
{
	int a;
	static void func(){}
};

void test1()
{	
	a1 a1;
	// 空对象占用内存空间为1
	// C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
	// 每个空对象也应该有一个独一无二的内存地址
	cout << "size of t:" << sizeof(a1) << endl;
}

void test2()
{
	a2 a2;
	// 4,说明非静态成员变量属于类的对象
	cout << "size of t:" << sizeof(a2) << endl; 
}

void test3()
{
	a3 a3;
	// 4,说明静态成员变量不属于类的对象
	cout << "size of t:" << sizeof(a3) << endl;
}

void test4()
{
	a4 a4;
	// 4,说明非静态成员函数不属于类的对象
	cout << "size of t:" << sizeof(a4) << endl;
}

void test5()
{
	a5 a5;
	// 4,说明静态成员函数不属于类的对象
	cout << "size of t:" << sizeof(a5) << endl;
}

int main(int argc, char* argv[])
{
	test1();
	test2();
	test3();
	test4();
	test5();
	return 0;
}

1.2 this指针概念

每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共同一块代码,那么问题是:这一块代码是如何区分是哪个对象调用自己的呢?

C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象

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

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

this指针的用途:

? ? ? ? 1. 当形参和成员变量名同名时,可用this指针来区分

#include <iostream>

using namespace std;

class Person
{
public:
	Person(int age)
	{
		// age = age; 报错
		this->age = age;
	}
	int age;
};

void test()
{
	Person p(23);
	cout << "p1的年龄:" << p.age << endl;
}

int main(int argc, char* argv[])
{
	test();
	return 0;
}

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

#include <iostream>

using namespace std;

class Person
{
public:
	Person(int age)
	{
		// age = age; 报错
		this->age = age;
	}
	int age;
	Person addAge1(Person& p)
	{
		this->age += p.age;
		return *this;
	}
	Person& addAge2(Person& p)
	{
		this->age += p.age;
		return *this;
	}
};

void test()
{
	Person p1(23);
	cout << "p1的年龄:" << p1.age << endl;
	Person p2(20);
	// addAge1返回的值,p1加完p2返回的是拷贝构造函数创建的新的对象,和自身不同,并没有在p1上进行累加
	p1.addAge1(p2).addAge1(p2).addAge1(p2).addAge1(p2);
	cout << "p1的年龄:" << p1.age << endl;
	// addAge2返回的引用,p1加完p2,返回p2本身
	p1.addAge2(p2).addAge2(p2).addAge2(p2).addAge2(p2);
	cout << "p1的年龄:" << p1.age << endl;
}

int main(int argc, char* argv[])
{
	test();
	return 0;
}

1.3 空指针访问成员函数

C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针

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

#include <iostream>

using namespace std;

class Person
{
public:
	void showClassName()
	{
		cout << "this is Person class" << endl;
	}
	void showAge()
	{
		// 提高代码健壮性
		if (this == NULL)
		{
			return;
		}
		// this指针指向的Person是一个空指针,对象没有实体,更不用说有age属性了
		cout << "age=" << this->age << endl;  // 在属性的前面都默认加了this
	}
	int age;
};

void test()
{
	Person* p = NULL;
	p->showClassName(); // 可以运行
	p->showAge(); // 有问题
}

int main(int argc, char* argv[])
{
	test();
	return 0;
}

1.4?const修饰成员函数

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

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

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

常对象:1. 声明对象前加const称该对象为常对象

? ? ? ? ? ? ? 2. 常对象只能调用常函数?

二、友元

生活中家里有客厅(Public),有卧室(Private)

客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你自己可以进去

但是,还有一些例外,比如你允许你的好朋友进去

在程序里,有些私有属性也想让类外特殊的一些函数或者类进行访问,就需要用到友元技术

友元的目的就是让一个函数或者类访问另一个类中的私有成员

友元的关机字为 friend

友元的三种实现:1. 全局函数做友元

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2. 类做友元

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?3. 成员函数做友元

2.1 成员函数做友元

#include <iostream>
#include <string>

using namespace std;

class Building
{
	// 告诉编译器,goodfriend是全局函数,是Building类的好朋友,可以访问类中的私有内容
	friend void goodfriend(Building* building);

public:
	Building()
	{
		this->m_SittingRoom = "客厅";
		this->m_BedRoom = "卧室";
	}

public:
	string m_SittingRoom; // 客厅
private:
	string m_BedRoom; // 卧室
};

void goodfriend(Building* building)
{
	cout << "正在访问:" << building->m_SittingRoom << endl;
	cout << "正在访问:" << building->m_BedRoom << endl;
}

int main(int argc, char* argv[])
{
	Building building;
	goodfriend(&building);
	return 0;
}

2.2 类做友元

#include <iostream>
#include <string>

using namespace std;

class Building
{
	// 告诉编译器,goodfriend是Building类的好朋友,可以访问类中的私有内容
	friend class goodfriend;

public:
	Building();
public:
	string m_SittingRoom; // 客厅
private:
	string m_BedRoom; // 卧室
};
// 类外写成员函数
Building::Building()
{
	m_SittingRoom = "客厅";
	m_BedRoom = "卧室";
}

class goodfriend
{
public:
	Building* building;
	goodfriend();
	void visit();
};
// 类外写成员函数
goodfriend::goodfriend()
{
	// 创建建筑物对象
	building = new Building;
}
void goodfriend::visit()
{
	cout << "正在访问:" << building->m_SittingRoom << endl;
	cout << "正在访问:" << building->m_BedRoom << endl;
}

void test()
{
	goodfriend zz;
	zz.visit();
}
int main(int argc, char* argv[])
{
	test();
	return 0;
}

2.3 成员函数做友元

#include <iostream>
#include <string>

using namespace std;

class Building;
class GoodFriend
{
public:
	Building* building;
	GoodFriend();
	void visit1(); // 让visit1函数可以访问Building中私有属性
	void visit2(); // 让visit2函数不能访问Building中私有属性
};

class Building
{
	// 告诉编译器,goodfriend是Building类的好朋友,可以访问类中的私有内容
	friend void GoodFriend::visit1();

public:
	Building();
public:
	string m_SittingRoom; // 客厅
private:
	string m_BedRoom; // 卧室
};
// 类外写成员函数
Building::Building()
{
	m_SittingRoom = "客厅";
	m_BedRoom = "卧室";
}


// 类外写成员函数
GoodFriend::GoodFriend()
{
	// 创建建筑物对象
	building = new Building;
}
void GoodFriend::visit1()
{
	cout << "正在访问:" << building->m_SittingRoom << endl;
	cout << "正在访问:" << building->m_BedRoom << endl;
}
void GoodFriend::visit2()
{
	cout << "正在访问:" << building->m_SittingRoom << endl;
	// cout << "正在访问:" << building->m_BedRoom << endl;
}
void test()
{
	GoodFriend gf;
	gf.visit1();
	gf.visit2();
}
int main(int argc, char* argv[])
{
	test();
	return 0;
}

文章来源:https://blog.csdn.net/zh20001109zh/article/details/134934210
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。