c++学习第六讲---类和对象---对象模型和this指针,友元

本文详细解释了C++中对象模型的结构,包括成员变量和成员函数的存储位置,空对象的内存占用,this指针的作用及其在解决名称冲突、返回对象本身和空指针访问成员函数中的应用。此外,还介绍了友元的概念,包括全局函数、类和成员函数作友元的情况。
摘要由CSDN通过智能技术生成

一.对象模型和this指针

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

在c++中,成员变量和成员函数是分开储存的,且只有 非静态成员变量 才属于一个对象。

1.空对象占用内存:

class Person
{

};
int main()
{
	Person p;
	cout << sizeof(p) << endl;//1
	return 0;
}

空对象会有一个字节的空间,是为了区分空对象栈内存的位置。

2.静态成员变量和成员函数不在类的对象上:

class Person
{
	int a;//非静态成员变量,在对象上
	static int b;//静态成员变量、不在
	void func() {//成员函数,不在

	}
};
int main()
{
	Person p;
	cout << sizeof(p) << endl;//4
	return 0;
}

2.this指针:

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

不需要定义,直接用即可。

用途:

1.解决名称冲突

class Person {
public:
	int age;
	Person(int age)
	{
		age = age;
	}
};
int main()
{
	Person p1(18);
	cout << p1.age << endl;//随机数,名称冲突时并没有赋值
	return 0;
}

可用this指针解决:

class Person {
public:
	int age;
	Person(int age)
	{
		this->age = age;//用this
	}
};
int main()
{
	Person p1(18);
	cout << p1.age << endl;//18
	return 0;
}

2.返回对象本身用*this

例:

class Person {
public:
	int age;
	Person(int age)
	{
		this->age = age;//用this
	}
	Person& PersonAddAge(Person& p)
	{
		this->age += p.age;//自身年龄加上传入的对象的年龄
		return *this;//返回一个对象自己
	}
};
int main()
{
	Person p1(18);
	Person p2(18);
	p2.PersonAddAge(p1).PersonAddAge(p1);//连续相加
	cout << p2.age << endl;//36
	return 0;
}

注:上面PersonAddAge函数返回的是引用Person&

如果把 & 去掉,只会加一次,

因为返回时返回的不是本体,而是拷贝构造后的新对象,后续相加就不是加在p2上了。

3.空指针访问成员函数:

空指针可以访问不引用成员变量的成员函数,

如果访问的成员函数引用了成员变量,则会报错。

class Person
{
public:
	void showClassName()
	{
		cout << "Person class" << endl;
	}
	void showPersonAge()
	{
		cout << "age = " << m_age << endl;
	}
	int m_age;
};
void test01()
{
	Person* p = NULL;
	p->showClassName();//不报错
	p->showPersonAge();//错误,无法从空对象找到其中属性
}

解决方法:可在引用了成员变量的函数中加上一个判定,使代码更健壮。

判断:this == NULL

	void showPersonAge()
	{
		if (this == NULL)
		{
			return;
		}
		cout << "age = " << m_age << endl;
	}

4.const修饰成员函数:

常函数:

1.成员函数后加const后称为常函数
2.常函数内不可以修改成员属性
3.成员属性声明时佳关键词mutable后,在常函数中可以修改

本质:在成员函数后面加const,修饰的是this指向,让指针指向的值也不可修改。

例:

class Person {
public:
	void showPerson()const
	{
		m_A = 100;//报错,不可修改
		m_B = 100;//可以修改
	}
	int m_A;
	mutable int m_B;
};

常对象:

1.声明对象前加const称该对象为常对象
2.常对象中的属性不可修改
3.常对象只能调用常函数

class Person {
public:
	void showPerson()const
	{

	}
	void func()
	{

	}
	int m_A;
	mutable int m_B;
};
int main()
{
	const Person p;
	p.m_A = 100;//不可修改
	p.m_B = 100;//可以修改
	p.showPerson();
	p.func();//报错,不能引用
	return 0;
}

二.友元

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

关键字:friend

1.全局函数作友元:

只需将函数在类中声明,再在函数前加上关键字 friend 即可。

class Building
{
	//友元的声明,是使全局函数可以访问私有成员
	friend void goodGay(Building* building);
public:
	Building()
	{
		m_SittingRoom = "客厅";
		m_BedRoom = "卧室";
	}
	string m_SittingRoom;//客厅
private:
	string m_BedRoom;//卧室
};

//全局函数
void goodGay(Building* building)
{
	cout << building->m_SittingRoom << endl;
	cout << building->m_BedRoom << endl;
}

2.类作友元:

将一个类作为友元,即可在友元类中的函数访问此类中的私有成员。

class Building
{
	friend class GoodGay;//GoodGay类可以访问私有成员
public:
	Building()
	{
		m_SittingRoom = "客厅";
		m_BedRoom = "卧室";
	}
	string m_SittingRoom;//客厅
private:
	string m_BedRoom;//卧室
};
class GoodGay
{
public:
	Building* building;
	void visit();//参观函数,访问building中的属性
	GoodGay()
	{
		building = new Building;
	}
};
void GoodGay::visit()
{
	cout << "访问" << building->m_BedRoom << endl;
}

3.成员函数作友元:

注意:需将友元函数所在类在前面定义。(GoodGay在Building之前定义)

class GoodGay
{
public:
	Building* building;
	void visit();//参观函数,访问building中的属性
	GoodGay()
	{
		building = new Building;
	}
};
class Building
{
	friend void GoodGay::visit();//将成员函数作为友元
public:
	Building()
	{
		m_SittingRoom = "客厅";
		m_BedRoom = "卧室";
	}
public:
	string m_SittingRoom;//客厅
private:
	string m_BedRoom;//卧室
};

void GoodGay::visit()
{
	cout << "访问" << building->m_BedRoom << endl;//可以访问私有成员
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值