栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 核心编程:4 类和对象(2)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 核心编程:4 类和对象(2)

4 类和对象 4.3 C++ 对象模型和this指针 4.3.1 成员变量和成员函数分开存储

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

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

#include
using namespace std;

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

class Person {

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

	static int m_B; //静态成员变量 不属于类的对象上

	void func() {} // 非静态成员函数  不属于类的对象上

	static void func2() {} // 静态成员函数 不属于类的对象上
};

int Person::m_B = 10;

void test01() {

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

}

void test02() {

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

int main() {

	test01();

	system("pause");

	return 0;

}
4.3.2 this 指针概念

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

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

this指针是隐含每一个非静态成员函数内的一种指针
this指针不需要定义,直接使用即可

this指针的用途:

  • 当形参和成员变量同名时,可用this指针来区分
  • 在类的非静态成员函数中返回对象本身,可使用 return *this
#include
using namespace std;

// 1 解决名称冲突

// 2 返回对象本身用 *this


class Person {
public:

	Person(int age) {
		// this指针指向的是
		// this指针指向被调用的成员函数所属的对象
		this->age = age;
	}

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

		//this指向p2的指针,而*this指向的就是p2这个对象本体
		return *this;
	}

	int age;
};

//1 解决名称冲突
void test01() {
	Person p1(18);
	cout << "p1的年龄为:" << p1.age << endl;
}

//2 返回对象本身用*this
void test02() {
	Person p1(10);

	Person p2(10);

	//链式编程思想
	p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);

	cout << "p2的年龄为:" << p2.age << endl;

}


int main() {

	test02();

	system("pause");

	return 0;
}

 

4.3.3 空指针访问成员函数

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

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

示例:

#include
using namespace std;

// 空指针调用成员函数

class Person {
public:

	void showClassName() {
		cout << "this is Person class " << endl;
	}

	void showPersonAge() {

		if (this == NULL)
			return;

		cout << "age = " << this->m_Age << endl;
	}

	int m_Age;

};


void test01() {

	Person* p = NULL;

	p->showClassName();

	//p->showPersonAge(); //报错的原因是因为传入的指针是为NULL

}

int main() {

	test01();

	system("pause");

}

 

4.3.4 const 修饰成员函数

常函数:

  • 成员函数后加 const 后我们称这个函数为常函数
  • 常函数内不可以修改成员属性
  • 成员属性声明时加关键字 mutable 后,在常函数中依然可以修改

常对象:

  • 声明对象前加 const 称该对象为常对象;
  • 常对象只能调用常函数

示例:

#include
using namespace std;


//常函数
class Person {
public:
	
	// this指针的本质 是指针常量 指针的指向是不可以修改的
	// const Person * const this;
	// 在成员函数后面加const,修饰的是this指向,让指针指向的值也不可以修改
	void showPerson() const {

		this->m_B = 100;
		//this->m_A = 100;
		//this = NULL; //this指针不可以修改指针的指向
	}

	void func() {
		m_A = 100;
	}

	int m_A;
	mutable int m_B; //特殊变量,即使在常函数中,也可以修改这个值 加上关键字mutable
};

void test01() {
	Person p;
	p.showPerson();
}

void test02() {
	const Person p; //在对象前加const,变为常对象
	//p.m_A = 100;
	p.m_B = 100;//m_B是特殊值,在常对象下也可以修改

	// 常对象只能调用常函数
	p.showPerson();
	//p.func();	//常对象不可以调用普通成员函数,因为普通成员函数可以修改属性
}

//
int main() {



	system("pause");

	return 0;

}
4.4 友元

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

客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说,只有你能进去,但是呢,你也可以允许你的好闺蜜好基友进去。

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

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

友元的关键字为 friend

友元的三种实现

  • 全局函数做友元
  • 类做友元
  • 成员函数做友元
4.4.1 全局函数做友元
#include
#include
using namespace std;



// 建筑物类
class Building {

	// goodGay全局函数是 Building 好朋友,可以访问Building中的私有成员
	friend void goodGay(Building* building);

public:

	Building() {
		m_SittingRoom = "客厅";
		m_BedRoom = "卧室";
	}

public:
	string m_SittingRoom; // 客厅

private:
	string m_BedRoom; // 卧室
};





// 全局函数
void goodGay(Building *building) {
	cout << "好基友的全局函数正在访问 :" << building->m_SittingRoom << endl;

	cout << "好基友的全局函数正在访问 :" << building->m_BedRoom << endl;
}

void test01() {
	Building building;
	goodGay(&building);
}





int main() {

	test01();


	system("pause");

	return 0;
}
4.4.2 类做友元
// 类做友元
#include
#include
using namespace std;

class Building;

class GoodGay {

public:
	GoodGay();

public:

	void visit(); // 参观函数 访问Building中的属性

	Building* building;


};

class Building {

	// GoodGay可以访问本类的私有成员
	friend class GoodGay;

public:
	Building();

public:
	string m_SittingRoom; // 客厅

private:
	string m_BedRoom; // 卧室
};

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

GoodGay::GoodGay() {
	// 创建建筑物对象
	building = new Building;
}

void GoodGay::visit() {

	cout << "好基友类正在访问:" << building->m_SittingRoom << endl;

	cout << "好基友类正在访问:" << building->m_BedRoom << endl;
}

void test01() {
	GoodGay gg;
	gg.visit();
}


int main() {

	test01();
	
	system("pause");

	return 0;
}
4.4.3 成员函数做友元
#include
#include
using namespace std;

class Building;

class GoodGay {
public:

	GoodGay();

	void visit(); // 让visit函数可以访问Building中的私有成员
	void visit2(); // 让visit2函数不可以访问Building中的私有成员

	Building* building;
};



class Building {
	
	friend void GoodGay::visit2();
public:
	Building();
public:
	string m_SittingRoom; // 客厅
private:
	string m_BedRoom; // 卧室
};

//类外实现成员函数
Building::Building() {
	m_SittingRoom = "客厅";
	m_BedRoom = "卧室";
}

GoodGay::GoodGay() {
	building = new Building;
}

void GoodGay::visit() {
	cout << "visit函数正在访问:" << building->m_SittingRoom << endl;
}

void GoodGay::visit2() {
	cout << "visit2函数正在访问:" << building->m_SittingRoom << endl;

	cout << "visit2函数正在访问:" << building->m_BedRoom << endl;
}

void test01() {
	GoodGay gg;
	gg.visit();
}

void test02() {
	GoodGay gg;
	gg.visit2();
}



int main() {

	//test01();
	test02();


	system("pause");

	return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/893363.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号