C++编程 友元函数、友元类、运算符重载 案例详细解析

目录

一:友元函数

二:友元类

三:运算符重载

四:= 运算符重载


一:友元函数

优势:友元函数可以访问类中的所有成员(公有,私有,保护),提高程序的运行效率

关键字:friend

缺点:破坏面向对象程序设计类的封装性

示例如下:

CStaff.h:

#ifndef CSTAFF_H
#define CSTAFF_H

class Staff
{
public:
	Staff();
	Staff(int id,char *name,char *pwd,int prole);
	~Staff();
	static int num;//静态数据成员 放在公有的
	static int getNum();

	//友元函数---类外函数
	//破坏封装性 尽量少用
	friend void printStaffInfo(Staff &staff);
private:
	int ID;
	char name[20];
	char pwd[20];
	int role;
protected:
};

#endif

CStaff.cpp:

#include"CStaff.h"
#include<iostream>
using namespace std;
 
//不存在对象当中 是所有对象都能够公共访问的
//独立于对象 存在在类当中的
int Staff::num = 1000;//静态成员的初始化
 
Staff::Staff()
{
	Staff::num++;
}
 
Staff::Staff(int id,char *name,char *pwd,int prole)
{
	this->ID = id;
	strcpy(this->name,name);
	strcpy(this->pwd,pwd);
	this->role = prole;
    Staff::num++;
}
 
Staff::~Staff()
{
 
}

main.cpp:

#include<iostream>
using namespace std;
#include"CStaff.h"

//友元函数访问员工类的数据成员
void printStaffInfo(Staff &staff)
{
	cout<<"id = "<<staff.ID<<endl;
	cout<<"name = "<<staff.name<<endl;
	cout<<"pwd = "<<staff.pwd<<endl;
	cout<<"role = "<<staff.role<<endl;
}

int main()
{
  //在类外部定义一个函数:打印用户信息
	Staff s1(1001,"admin","123456",1);
	printStaffInfo(s1);
	//id = 1001
    //name = admin
    //pwd = 123456
    //role = 1
}

二:友元类

如窗口基类 访问 控件基类 (在控件基类中 写入 窗口基类的友元)

friend class CWinBase;  //类的声明  可以通过友元类(访问类外) 但破坏封装性了
int CWinBase::WinRun()
{
	int i=0,key=0;
	for(i=0;i<this->ctrlCount;i++)
	{
		if(this->ctrlArr[i]->ctrlType==EDIT||this->ctrlArr[i]->ctrlType==BUTTON)
		{
			CTools::gotoxy(this->ctrlArr[i]->startX+2,this->ctrlArr[i]->startY+1);
			break;
		}
	}
}

使用友元类,就可以不用写get方法,但是却会破坏面向对象程序设计的封装性,因此最好还是写get方法提供类外访问的接口

三:运算符重载

以复数为例,示例如下

CComplex.h:

#ifndef CCOMPLEX_H
#define CCOMPLEX_H

class CComplex
{
public:
	CComplex();//构造
	CComplex(int a,int b);//带参
	~CComplex();//析构
	void print();
	CComplex operator+(CComplex &complex);  //隐式传参 this指针 a+b
	CComplex operator++(int);  //int作为区分  后置++  i++
	CComplex& operator++();    //             前置++  ++i
	friend CComplex operator*(CComplex &c1,CComplex &c2);
protected:
private:
	int real;  //实部
	int imag;  //虚部
};

#endif

CComplex.cpp:

#include"CComplex.h"
#include<iostream>
using namespace std;

CComplex::CComplex()//构造
{
	this->real = 10;
	this->imag = 20;
}

CComplex::CComplex(int a,int b)//带参
{
	this->real = a;
	this->imag = b;
}

CComplex::~CComplex()
{

}

CComplex CComplex::operator+(CComplex &complex)//双面运算符+
{
	CComplex tmp;
	//this 指针
	tmp.real = this->real + complex.real;
	tmp.imag = this->imag + complex.imag;
	return tmp;
}

void CComplex::print()
{
	cout<<this->real<<"+"<<this->imag<<"j"<<endl;
	//1+2j + 3+4j  = 4+4j
}

CComplex CComplex::operator++(int)//单目后置++
{
	//先使用值 再自增
	CComplex tmp;
	tmp.real = this->real;
	tmp.imag = this->imag;
	this->real++;
	this->imag++;
	return tmp;
}

CComplex& CComplex::operator++()//单目前置++
{
	this->real++;
	this->imag++;
	return *this;
}

main.cpp:

a. 类成员函数实现双目运算符+的重载

#include<iostream>
using namespace std;
#include"CComplex.h"

int main()
{
	CComplex c1,c3;
	CComplex c2(1,2);
	//类成员函数实现 双目运算符+的重载
	c3 = c1 + c2;
	c3.print();//11+22j	
}

b. 类成员函数实现单目运算符重载  i++ 单目后置++

#include<iostream>
using namespace std;
#include"CComplex.h"

int main()
{
	CComplex c1,c3;
	CComplex c2(1,2);
	//类成员函数实现单目运算符重载  i++ 
    //先打印 在自增
    (c1++).print();  //10+20j
    c1.print();      //11+21j
}

c. 类成员函数实现单目运算符重载  ++i 单目前置++

#include<iostream>
using namespace std;
#include"CComplex.h"

int main()
{
	CComplex c1,c3;
	CComplex c2(1,2);
	//类成员函数实现单目运算符重载  ++i 前置++ 
    //先自增  再打印
    (++c1).print();  //11+21j
    c1.print();      //11+21j
}

d. 单目后置++ 显式调用

#include<iostream>
using namespace std;
#include"CComplex.h"

int main()
{
//	CComplex c1;
	CComplex c2(1,2);
   	(c2.operator ++(0)).print();  //1+2j
	c2.print();                   //2+3j
}

e. 单目前置++ 显式调用

#include<iostream>
using namespace std;
#include"CComplex.h"

int main()
{
	CComplex c1;
//	CComplex c2(1,2);
    (c1.operator++()).print(); //11+21j
    c1.print();                //11+21j
}

f. 类的友元函数实现运算符*重载  【实部*实部 虚部*虚部】

#include<iostream>
using namespace std;
#include"CComplex.h"

//类的友元函数实现运算符*重载  实部*实部 虚部*虚部
CComplex operator*(CComplex &c1,CComplex &c2)
{
	CComplex tmp;
	tmp.real = c1.real * c2.real;
	tmp.imag = c1.imag * c2.imag;
	return tmp;
}

int main()
{
	CComplex c1,c3;
	CComplex c2(1,2);
	//类成员函数实现 双目运算符*的重载
	c3 = c1 * c2;
    c3.print();  //10+40j
}

四:= 运算符重载

调用拷贝构造函数的情况:
1. 通过一个已经存在的对象去创造一个新的对象 此时会调用这个新对象的拷贝构造函数
2. 当一个对象作为函数实参传入时 此时会调用形参的拷贝构造函数
3. 当函数的返回值是一个对象时 此时接收这个函数返回值的对象会调用拷贝构造函数


从上面的情况 可以总结出:
当一个已经构造好了的对象去赋值给一个还未构造的对象,此时就会调用这个还未构造的对象的拷贝构造函数    产生的结果就是会有新的对象产生

CComplex c4 = c1;

= 运算符重载 示例如下

CComplex.h:

#ifndef CCOMPLEX_H
#define CCOMPLEX_H

class CComplex
{
public:
	CComplex();
	CComplex(int a,int b,char* word);
	void print();
	~CComplex();
	CComplex operator+(CComplex &complex);  //双面+
	CComplex operator++(int);               //单目后置++
	CComplex& operator++();                 //单目前置++
	friend CComplex operator*(CComplex &c1,CComplex &c2);//类的友元函数实现运算符*重载
	CComplex& operator = (CComplex &c1);    //=运算符重载
protected:
private:
	int real;  //实部
	int imag;  //虚部
	char *p;   //字符串
};

#endif

CComplex.cpp:

#include"CComplex.h"
#include<iostream>
using namespace std;
#include<stdlib.h>

CComplex::CComplex()
{
	this->real = 10;
	this->imag = 20;
	this->p = new char[20];//开空间
	memset(p,0,20);//初始化
}

CComplex::CComplex(int a,int b,char* word)
{
	this->real = a;
	this->imag = b;
	this->p = new char[20];//开空间
	memset(p,0,20);//初始化
	strcpy(p,word);//赋值
}

CComplex CComplex::operator+(CComplex &complex)//双面+
{
	CComplex tmp;
	//this 指针
	tmp.real = this->real + complex.real;
	tmp.imag = this->imag + complex.imag;
	return tmp;
}

void CComplex::print()
{
	cout<<this->real<<"+"<<this->imag<<"j"<<endl;
	//1+2j + 3+4j  = 4+4j
	cout<<this->p<<endl;
}

CComplex CComplex::operator++(int)//单目后置++
{
	//先使用值 再自增
	CComplex tmp;
	tmp.real = this->real;
	tmp.imag = this->imag;
	this->real++;
	this->imag++;
	return tmp;
}

CComplex& CComplex::operator++()  //单目前置++
{
	this->real++;
	this->imag++;
	return *this;
}

CComplex::~CComplex()
{
}

CComplex& CComplex::operator = (CComplex &c1)//= 运算符重载
{
	this->real = c1.real;
	this->imag = c1.imag;
	this->p = new char[20];//开空间
	memset(p,0,20);//初始化
	strcpy(p,c1.p);//赋值
	return *this;  //引用返回值
}

main.cpp:

#include<iostream>
using namespace std;
#include"CComplex.h"

int main()
{
//实现  =运算符 的重载
	CComplex c1;
	CComplex c2(1,2,"hello");
//两个对象都是已经创建好了的
	c1 = c2;
    c1.print();//1+2j   hello
}

对于拷贝构造函数 和 = 运算符重载 ,做好区分: 

= 运算符重载:两个对象都是已经创建好了的

拷贝构造函数:  一个已经构造好了的对象去赋值给一个还未构造的对象

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chenruhan_QAQ_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值