C++类(二):C++友元函数和拷贝构造函数一起用时的问题

探讨C++中友元函数与拷贝构造函数共存时的问题及解决方法,介绍如何通过引用传递避免不必要的拷贝构造调用。

本人初学C++,碰到一个问题,友元函数和拷贝构造函数共存情况下,若拷贝构造函数定义中不写继承成员变量的代码,实例化类的对象后,无法通过友元函数正常打印成员变量。
解决:后面同学给出了方案,通过引用作为参数,避免在传参过程中创建参数副本,即没有进入拷贝构造函数。

  1. 无拷贝构造函数情况下:
    友元函数可以正常访问私有成员变量,代码和输出如下:

代码:

    #include "pch.h"
    #include <iostream>
    using namespace std;
    class STU {
    public:
    	int ID;
    	float score;
    	int cnt;
    	STU(int x, float y);	/*构造函数*/
    	~STU(void);				/*析构函数	*/
    	friend void MsgPrint(STU stu);
    private:
    	int num;
    	int cars;
    	double money;
    };
    STU::STU(int x, float y)
    {
    	num = 11;
    	cnt = 0;
    	cars = 3;
    	money = 20.6f;
    	ID = x;
    	score = y;
    	cout << "Object is being created" << endl;
    };
    STU::~STU(void)
    {
    	cout << "Object is being deleted" << endl;
    }
    void MsgPrint(STU stu)
    {
    	printf("cars:%d\n", stu.cars);
    	printf("money:%f\n", stu.money);
    	printf("num:%d\n", stu.num);
    }
    int main()
    {
    	STU hm(2, 6);
    	MsgPrint(hm);
    }

输出:

Object is being created
cars:3
money:20.600000
num:11
Object is being deleted
Object is being deleted
G:\C++\Runoob\Lesson1_1\lesson1_1\Debug\lesson1_1.exe (进程11640)已退出,返回代 码为: 0。

  1. 友元函数和拷贝构造函数共存情况下:

代码:

#include "pch.h"
#include <iostream>
using namespace std;
class STU {
public:
	int ID;
	float score;
	int cnt;
	STU(int x, float y);	/*构造函数*/
	STU(const STU &obj);	/*拷贝构造函数*/
	~STU(void);				/*析构函数	*/
	friend void MsgPrint(STU stu);
private:
	int num;
	int cars;
	double money;
};
STU::STU(int x, float y)
{
	num = 11;
	cnt = 0;
	cars = 3;
	money = 20.6f;
	ID = x;
	score = y;
	cout << "Object is being created" << endl;
};
STU::STU(const STU &obj)
{
	cout << "调用拷贝构造函数" << endl;
	//cars = obj.cars;   /*注意这部分代码*/
	//num = obj.num;     /*注意这部分代码*/
	//money = obj.money; /*注意这部分代码*/
}
STU::~STU(void)
{
	cout << "Object is being deleted" << endl;
}
void MsgPrint(STU stu)
{
	printf("cars:%d\n", stu.cars);
	printf("money:%f\n", stu.money);
	printf("num:%d\n", stu.num);
}
int main()
{
	STU hm(2, 6);
	MsgPrint(hm);
}

31-33行注释情况下的输出,不正确:

Object is being created
调用拷贝构造函数
cars:2358696
money:8192.000000
num:20914556
Object is being deleted
Object is being deleted
G:\C++\Runoob\Lesson1_1\lesson1_1\Debug\lesson1_1.exe (进程11712)已退出,返回代 码为: 0。

31-33行不注释情况下的输出,正确:

Object is being created
调用拷贝构造函数
cars:3
money:20.6
num:11
Object is being deleted
Object is being deleted
G:\C++\Runoob\Lesson1_1\lesson1_1\Debug\lesson1_1.exe (进程10044)已退出,返回代 码为: 0。

  1. 解决:引用作为参数
  #include "pch.h"
  #include <iostream>
  using namespace std;
  class STU {
  public:
  	int ID;
  	float score;
  	int cnt;
  	STU(int x, float y);	/*构造函数*/
  	STU(const STU &obj);	/*拷贝构造函数*/
  	~STU(void);				/*析构函数	*/
  	friend void MsgPrint(STU& stu);
  
  private:
  	int num;
  	int cars;
  	double money;
  };
  STU::STU(int x, float y)
  {
  	num = 11;
  	cnt = 0;
  	cars = 3;
  	money = 20.6f;
  	ID = x;
  	score = y;
  	cout << "Object is being created" << endl;
  };
  STU::STU(const STU &obj)
  {
  	cout << "调用拷贝构造函数" << endl;
  	//cars = obj.cars;
  	//num = obj.num;
  	//money = obj.money;
  }
  STU::~STU(void)
  {
  	cout << "Object is being deleted" << endl;
  }
  void MsgPrint(STU& stu)
  {
  	printf("cars:%d\n", stu.cars);
  	printf("money:%f\n", stu.money);
  	printf("num:%d\n", stu.num);
  }
  int main()
  {
  	STU hm(2, 6);
  	MsgPrint(hm);
  }

输出:

Object is being created
调用拷贝构造函数
cars:3
money:20.600000
num:11
Object is being deleted
Object is being deleted
G:\C++\Runoob\Lesson1_1\lesson1_1\Debug\lesson1_1.exe (进程11656)已退出,返回代 码为: 0。

张天乐 gold94282 C++ 面向对象 - 运算符重载与友元函数(实验) 实验总用时:00:00:06 nav 第2关:学生信息转换 100 学习内容 参考答案 记录 评论 任务描述 相关知识 友元函数 友元 转换构造函数 编程要求 测试说明 任务描述 本关任务:设计学生教师两个,并实现它们之间的转换。 相关知识 为了完成本关任务,你需要掌握友元函数、友元以及转换构造函数。 友元函数 有时候我们希望某个函数能访问一个的非公有成员,但又不想把它做成这个的成员函数,这个时候就可以使用友元。 如果要将一个函数变成一个的友元,只需要在中函数前加一个 friend 关键字来声明函数即可,并且访问性不受限制。即表现形式为: friend <返回型> <函数名> (<参数列表>); 但这个友元函数他不属于该的成员函数,他是定义在外的普通函数,只是在中声明该函数可以直接访问中的 private 或者 protected 成员。 例如: class Test{ private: int a; protected: int b; public: friend void fun(Test t); // 友元函数 }; void fun(Test t) { t.a = 100; t.b = 2000; cout << "a = " << t.a << ", b = " << t.b << endl; } int main() { Test test; fun(test); return 0; } 输出结果为:a = 100, b = 2000 友元 C++ 中也允许声明一个为某个的友元,方法声明友元函数旗鼓相当。但是需要注意的是,作为友元的的声明必须在友元的声明之前。 例如: class TestFriend { private: int a; }; // TestFriend 的声明在 Test 之前 class Test { private: int a; friend class TestFriend; // 声明友元 }; 有时候作为友元的的声明不便放在友元声明之前,这个时候就可以使用前置声明。不过前置声明的只是一个名字(或者说不完全型),不能访问它内部的内容。 例如: class TestFriend; // 前置声明 TestFriend ,只是一个名字 class Test { private: int a; friend class TestFriend; // 声明友元 friend void TestFriend::Func(); // 尝试将 TestFriend 的成员函数 Func 作为友元函数,但由于 TestFriend 目前只有前置声明,所以会出错。 }; class TestFriend // TestFriend 的声明在 Test 之后 { private: int a; public: void Func(); }; 最后,友元声明还有如下限制: 友元关系不能被继承。 友元关系是单向的,不具有交换性。若 B 是 A 的友元, A 不一定是 B 的友元。 友元关系不具有传递性。若 B 是 A 的友元, C 是 B 的友元, C 不一定是 A 的友元。 转换构造函数 一个构造函数接收一个不同于其型的形参,可以视为将其形参转换成的一个对象,像这样的构造函数称为转换构造函数。因此转换构造函数的作用就是将一个其他型的数据转换成一个的对象。 除了创建对象之外,转换构造函数还为编译器提供了执行隐式型转换的方法。只要在需要型值的地方,给定构造函数的形参型的值,就将由编译器执行这种型的转换。 转换构造函数是构造函数的一个特例,当一个构造函数的参数只有一个,而且是一个其他型的 const 引用时,它就是一个转换构造函数。 例如: class T1{}; class T2 { public: T2(const T1 &t); // 从 T1 转换到 T2 的转换构造函数 }; 有了转换构造函数,就可以实现不同型之间的型转换了,比如: /* 定义同上 */ int main() { T1 t1;
最新发布
11-01
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值