(六)C++基础之类的this指针、友元函数

一、C++类的this指针和友元函数

1.1、this指针

我们来测试一段代码:

#include <iostream>

using namespace std;

class Test
{
public:
	void printA(void)
	{
		cout << "a = " << a << endl;
	}
	void printB(void)
	{
		cout << "a = " << a << endl;
	}
private:
	int a;
	int b;
};

class Test1
{
public:
	void printA(void)
	{
		cout << "a = " << a << endl;
	}
	void printB(void)
	{
		cout << "a = " << a << endl;
	}
	void printA1(void)
	{
		cout << "a = " << a << endl;
	}
	void printB1(void)
	{
		cout << "a = " << a << endl;
	}
	void printA2(void)
	{
		cout << "a = " << a << endl;
	}
	void printB2(void)
	{
		cout << "a = " << a << endl;
	}
private:
	int a;
	int b;
};

int main(void)
{
	Test t1;
	Test1 t2;

	cout << "t1 sizeof : " << sizeof(t1) << endl;

	cout << "t2 sizeof : " << sizeof(t2) << endl;
	return 0;
}

运行结果:
在这里插入图片描述
这段测试代码主要是测试函数方法是否在对象内存储,对于第一个类,只定义了两个函数,第二个类,定义6个函数,所以将类定义的对象大小打印出来。

但是打印出来发现他们两个的大小都一样,而且都是8,刚好是两个int的大小,那么就知道函数其实并不是在对象里面,可是如果她不在里面,每定义的对象又是如何能够输出自己的数据呢?

我们思考一下,在C语言中,我们定义结构体,是怎么将结构体里面的数据输出打印?

#include <stdio.h>

struct test{
	int a;
	int b;
};

void test_init(struct test *pstruct,int a, int b)
{
	pstruct->a = a;
	pstruct->b = b;
}

void print_test(struct test *pstruct)
{
	printf("a = %d b = %d\r\n", pstruct->a, pstruct->a);
}

int main(void)
{
	struct test t1;
	test_init(&t1,10,20);
	print_test(&t1);
}

通过代码,我们一般都是使用传递指针的方式进行输出,所以起码我们知道在C++中也肯定存在类似地址指针的东西,如果他将对象的地址传递过来,那么我肯定只能访问的是我本身的数据。

这就是C++类中的this指针,他的作用和C语言中的结构体传递的本身指针一样。

如同下面这个例子:

#include <iostream>

using namespace std;

class Test
{
public:

	Test(int a, int b)
	{
		this->a = a;
		this->b = b;
	}

	void print(void)
	{
		cout << "a = " << this->a << " b = " << this->b << endl;
	}

private:
	int a;
	int b;
};


int main(void)
{
	Test t1(10,20);

	t1.print();

	return 0;
}

在构造函数中,通过this告诉编译器这是我本身的变量,如果没有this,那么就是 **a=a;**那么在构造函数中就没有任何意义。

	Test(int a, int b)
	{
		this->a = a;
		this->b = b;
	}

如何证明this就是一个指针呢?很简单,如果可以使用*this来操作不就代表他是一个指针了么?

于是我接着去测试一下:

#include <iostream>

using namespace std;

class Test
{
public:

	Test(int a, int b)
	{
		this->a = a;
		this->b = b;
	}

	void print(void)
	{
		cout << "a = " << this->a << " b = " << this->b << endl;
	}

	Test & a_add(int a)
	{
		this->a += a;
		return *this;
	}

private:
	int a;
	int b;
};


int main(void)
{
	Test t1(10, 20);

	t1.print();

	t1.a_add(2).a_add(4);

	t1.print();
	return 0;
}

重点是这个函数:

Test & a_add(int a)
	{
		this->a += a;
		return *this;
	}

这个函数实现的功能就是实现a的变化,然后然返回自己本身,这样我们就可以实现多次变化,如下面这种写法:

t1.a_add(2).a_add(4);

首先 t1.a_add(2) 调用,t1的a会加上2,然后返回本身,于是接下来变为t1.a_add(2).a_add(4); -> t1.a_add(4) ,所以最终a = 10+2+4;运行结果如下:

在这里插入图片描述

而且通过这个例子,发现this的确是可以通过*this将其本身返回来,所以this应该是一个指针。
既然是指针,那么可以this++么?

答案是不能:
在这里插入图片描述所以我们知道this是 Test * const类型;可是我们看this->a,是可以修改里面的值,所以不可能是 const Test * const,那么有些时候我们也不需要他修改我里面的值,可是this已经隐藏起来没办法在形参里面定义,可以在函数右边加上const,不要再构造函数上面加const,会出现语法错误, 记得这个const是修饰this指针的,不是修饰函数的,函数没有const ,这样this就变成 const Test * const,而加上之后语法也提示不能修改this里面的值了。
在这里插入图片描述

1.2、友元函数

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函  数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上  关键字  friend,其格式如下: 

friend 类型 函数名(形式参数);

为什么会出现友元这个概念,他一般运用于那个地方,我们来看一段代码:

#include <iostream>

using namespace std;

class Test
{
public:

	Test(int a)
	{
		this->a = a;

	}
	void print(void)
	{
		cout << "a = " << this->a  << endl;
	}
	
	int get_a(void)
	{
		return a;
	}

private:
	int a;
};

void my_test(Test &c)
{
	cout << "a = " << c.get_a() << endl;
}

int main(void)
{

	Test t1(10);

	t1.print();

	my_test(t1);

	return 0;
}

这个函数的目的就是获取对象里面的a的值,然后将其输出,因为a是private变量,所以需要我们提供一个函数来提供a的值,可是如果当 my_test() 这个函数反复调用的时候,将会导致c.get_a() 反复入栈,导致效率降低,可是因为a又是private变量,不能访问,现在如果就只有这个函数能访问,其他的不能访问即可。

所以友元这个概念就出现了,其实说的直白一点,就是我这个函数是你这个类的哥们,我也有权访问你的private变量。

#include <iostream>

using namespace std;

class Test
{
public:

	friend void my_test(Test &c);

	Test(int a)
	{
		this->a = a;

	}
	void print(void)
	{
		cout << "a = " << this->a  << endl;
	}
	
	int get_a(void)
	{
		return a;
	}

private:
	int a;
};

void my_test(Test &c)
{
	cout << "a = " << c.a << endl;
}

int main(void)
{

	Test t1(10);

	t1.print();

	my_test(t1);

	return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述
友元的申明可以在类的任何地方。

关于友元使用几点:

1、申明位置
友元声明以关键字  friend 开始,它只能出现在类定义中。因为友元不是授权类的成员,所以它不受其所在类的声明区域public private 和protected 的影响。通常我们  选择把所有友元声明组织在一起并放在类头之后。

2、友元的利弊
友元不是类成员,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。不过,类的访问权限确实在某些应用场合显得有些呆板,从而容忍了友元这一特别语法现象。

3、注意事项
(1) 友元关系不能被继承。 
(2) 友元关系是单向的,不具有交换性。类B是类A 的友元,类A 不一定是类B 的友元,要看在类中是否有相应的声明。 
(3) 友元关系不具有传递性。若类B是类A 的友元,类C 是B 的友元,类C不一定是类A 的友元,同样要看类中是否有相应的声明。

所建议能不使用就不使用。

发布了29 篇原创文章 · 获赞 0 · 访问量 419

猜你喜欢

转载自blog.csdn.net/weixin_42547950/article/details/104338918
今日推荐