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

C++友元和运算符重载

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

C++友元和运算符重载

C++友元

友元就是friend修饰函数或者类,友元只是单纯的提供一个场所赋予对象具有无视权限功能(不是说直接就可以访问另一个数据)

友元函数
  • 友元函数不属于类,就是一个普通函数,类外实现不需要类名限定
  • 以另一个类的成员函数当做友元函数,需要注意写法
#include

// 正常友元函数的写法
using namespace std;
class YXC {
public:
	YXC(string name = "默认",int age = 12):name(name),age(age){}
	// 友元函数
	friend void print(YXC& object);
	void printYXC() {
		cout << name << "t" << age << endl;
	}
private:
	string name;
	int age;
};
// 类外实现不需要类名限定
void print(YXC& object) {
	YXC* p = new YXC;
	p->name = "无视权限";
	p->age = 123;
	p->printYXC();
	cout << object.name << "t" << object.age << endl;
}

// 不正常的写法: 以另一个类的成员函数当做友元函数
class YXC_B{
public:
	YXC_B(int b = 1234) :YXC_B_value(b){}
	void printYXC_B();
private:
	int YXC_B_value;
};

class YXC_A {
	friend void YXC_B::printYXC_B();	// 不受A的权限限定
public:
	YXC_A(int a = 122):YXC_A_value{a}{}
private:
	int YXC_A_value;
};

void YXC_B::printYXC_B() {
	YXC_A aobject;
	cout << aobject.YXC_A_value << endl;
	cout << "b中的函数" << endl;
}

int main() {
	YXC yxc;
	// cout << yxc.name << endl; // 错误 没有权限,不可访问
	print(yxc);
	YXC_B bObject;
	YXC_A aObject;
	bObject.printYXC_B(); // 类 B的函数成功打印了A中的私有属性的值为122
	return 0;
}
友元类
  • 在另一个类中用friend修饰声明的类,称之为友元类
#include
using namespace std;
class Boy_YXC {
	friend class Girl_YXC; // 友元类
public:
	Boy_YXC(string name,int age):name(name),age(age){}
private:
	void printBoy_YXC() {
		cout << name << "t" << age << endl;
	}
	string name;
	int age;
};
class Girl_YXC {
public:
	Girl_YXC(string name,int age):boy_yxc(name,age){}
	void printInfo() {
		cout << boy_yxc.name << "t" << boy_yxc.age << endl;// 无视权限
		Boy_YXC* pB = new Boy_YXC("new", 18);
		pB->printBoy_YXC(); // 无视权限
		cout << pB->age << "t" << pB->name << endl;
	}
private:
	Boy_YXC boy_yxc;
};
// 互为友元类

class Test {
	friend class Data;
public:
	void printTest();
private:
	void test() {
		cout << "测试权限专用函数" << endl;
	}
};
class Data {
	friend class Test;
public:
	void printData() {
		Test tObject;
		tObject.test();
	}
private:
	void data() {
		cout << "测试权限专用函数" << endl;
	}
};
void Test::printTest() {
	Data dObject;
	dObject.data();
	cout << "printTest" << endl;
}
int main() {
	Test test;
	test.printTest();

	Data data;
	data.printData();
	return 0;
}
C++运算符重载

声明是运算符重载? 运算符重载是赋予自定义数据能被运算符直接操作,运算符重载实质伤就是函数调用

运算符重载函数的长相:

  • 函数返回值类型,这个运算符最终运算结果的类型 YXC a , YXC b; YXC c = a + b ;(YXC)
  • 函数名: operator加上运算符组成函数名 operator+ 这个整体函数名
  • 函数参数: 看运算符需要几个参数去运算,传几个参数
    • 友元重载:参数个数是等于操作数
    • 类重载:参数个数是等于操作数-1
  • 参数类型:操作数的类型决定
  • 函数体:写你想要的运算(不成文规定:不能违背运算符本来含义)
友元重载 类重载
#include
#include 
using namespace std;
class YXC {
public:
	YXC(){}
	YXC(string name,int age) :name(name),age(age){}
	void printYXC() {
		cout << name << "t" << age << endl;
	}
	// 友元重载 yxc + xchuan
	friend YXC operator+(YXC& oobject1, YXC& object2);
	// 类成员函数重载: 减法重载
	YXC operator-(YXC& object);
private:
	string name;
	int age;
};

// 局部变量的地址和引用
YXC operator+(YXC& object1, YXC& object2) {
	// return YXC(object1.name, object2.age + object2.age);
	YXC yxc;
	yxc.name = object1.name;
	yxc.age = object1.age + object2.age;
	return yxc;
}
YXC YXC::operator-(YXC& object) {
	return YXC(this->name, this->age - object.age);
}

int main() {
	// 友元重载
	YXC yxc("易小川", 18);
	YXC xchuan("小川", 20);
	// vs中重载的运算符是绿色
	YXC result = yxc + xchuan;	// 运算符重载隐式调用
	// yxc + xchuan解析过程: operator+(yxc,xchuan);
	string str1 = "dsd";
	string str2 = "sdsd";
	cout << (str1 > str2) << endl;
	YXC result2 = operator+(yxc, xchuan); // 显示隐式
	result2.printYXC();
	YXC temp1 = result2 - yxc;	// 隐式调用: 解析为: result2.operator-(yxc);
	temp1.printYXC();

	YXC temp2 = yxc - result2;
	temp2.printYXC();
	return 0;
}
特殊重载
  • = () -> [] 只能重载为类的成员函数
  • . .* ?: :: 不能被重载
  • 重载必须要存在一个自定义类型
  • 一个重载习惯: 单目运算类重载,双目采用友元重载
  • ++ – 重载
    • 前置和后置一个处理,后置通常会增加一个无用int参数作为标记
  • 输入输出重载
    • 流对象的类型
      • cout: ostream —> 输出流对象
      • cin: istream —> 输入流对象
    • 友元重载
    • 尽量保存用引用类型
  • 文本重载
    • 文本重载是后缀重载
  • 对象隐式转换
#include
#include
#include
using namespace std;
class YXC
{
public:
	YXC(){}
	YXC(string name,int age) :name(name),age(age){}
	void printYXC() {
		cout << name << "t" << age << endl;
	}
	YXC operator++(int)		// 后置++的标记
	{
		return YXC(this->name, this->age++);
	}
	YXC operator++() {
		this->age++;
		return (*this);
	}
	friend istream& operator>>(istream& in, YXC& object);
	friend ostream& operator<<(ostream& out, YXC& object);
private:
	string name;
	int age;
};
istream& operator>>(istream& in, YXC& object) 
// cin >> temp;
{
	cout << "请输出YXC的数据: ";
	in >> object.name >> object.age;
	return in;
}
ostream& operator<<(ostream& out, YXC& object) {
	cout << "name\tage" << endl;
	out << object.name << "t" << object.age << endl;
	return out;
}

// 后缀尽量用下划线
unsigned long long operator""_h(unsigned long long hour) {
	return hour * 60 * 60;
}
unsigned long long operator""_m(unsigned long long min) {
	return min * 60;
}
unsigned long long operator""_s(unsigned long long sec) {
	return sec;
}
// 对象的隐式转换

class YXC_super
{
public:
	YXC_super(string name,int age) :name(name),age(age){}
	// operator 要转的类型()
	//	对象的隐式转换
	operator int() {
		return age; //返回值
	}
	operator double() {
		return (double)age;
	}
private:
	string name;
	int age;
};

int main() {
	// No.1 前置和后置重载
	YXC yxc("易小川", 18);
	YXC xchuan = yxc++;
	xchuan.printYXC();
	yxc.printYXC();
	YXC xxchuan = ++yxc;
	yxc.printYXC();
	xxchuan.printYXC();
	// No.2 流重载
	YXC temp;
	cin >> temp;
	cout << temp;
	// No.3 后缀重载
	int count = 1_h + 39_m + 30_s;
	cout << count << endl;

	// No.4 对象的隐式转换
	YXC_super ycc("易川川", 22);
	int age = ycc;
	cout << age << endl;
	double age2 = ycc;
	cout << age2 << endl;
	return 0;
}
C++运算符重载综合案例
// 1.简单封装一个数据类型
// 2.封装函数包装器: 把函数封装成一个对象
// 3.封装一下智能指针,实现内存自动申请和释放

#include
#include
#include
using namespace std;
// No.1 简单封装一个数据
class Int {
public:
	Int(int num = 0) :m_num(num){}
	int& data()	// string : data() c_str()
	{
		return m_num;
	}
	int toint() {
		return m_num;
	}
	string to_string() {
		return ::to_string(m_num); // 区分一下,C++中有一个to_string
	}
	int operator()() {
		return m_num;
	}
public:
	// 算术
	Int operator+(const Int& value) {
		return Int(this->m_num + value.m_num);
	}
	Int operator-(const Int& value) {
		return Int(this->m_num - value.m_num);
	}
	Int operator/(const Int& value) {
		return Int(this->m_num / value.m_num);
	}
	Int operator*(const Int& value) {
		return Int(this->m_num * value.m_num);
	}
	Int operator%(const Int& value) {
		return Int(this->m_num % value.m_num);
	}
public:
	// 条件运算符重载
	bool operator==(const Int& value) {
		return this->m_num == value.m_num;
	}
	bool operator!=(const Int& value) {
		return this->m_num != value.m_num;
	}
	bool operator>(const Int& value) {
		return this->m_num > value.m_num;
	}
	bool operator<(const Int& value) {
		return this->m_num < value.m_num;
	}
	bool operator>=(const Int& value) {
		return this->m_num >= value.m_num;
	}
public:
	// 赋值运算符
	Int& operator=(const Int& value) {
		this->m_num = value.m_num;
		return *this;
	}
	Int& operator+=(const Int& value) {
		this->m_num += value.m_num;
		return *this;
	}
public:
	// 单目运算符
	Int operator-() {
		return Int(-this->m_num);
	}
	Int* operator&() {
		return this;
	}
public:
	friend ostream& operator<<(ostream& out, const Int& object) {
		out << object.m_num;
		return out;
	}
	friend istream& operator>>(istream& in, Int& object) {
		in >> object.m_num;
		return in;
	}
private:
	int m_num;
};
void test_my_int() {
	Int number(123);
	cout << number() << endl;
	Int temp;
	cin >> temp;
	cout << temp << endl;
	cout << (number == temp) << endl;
}

// No.2 封装函数包装器
class Func {
	using PF = void(*)();
public:
	Func(PF pf):pf(pf){}
	void operator()() {
		pf();
	}
	Func operator=(PF& pf){
		this->pf = pf;
	}
private:
	PF pf;
};

void print() {
	cout << "函数调用" << endl;
}

void printYXC() {
	cout << "我叫易小川" << endl;
}

void test_func() {
	// 函数包装器:	把函数指针包装成为对象
	Func object(print);
	object();	// 在通过对象调用函数

	Func object2 = print;
	object2();
	object2 = printYXC;
	object2();
}

// No.3 智能指针
class Auto_ptr_int {
public:
	Auto_ptr_int(int* ptr) :ptr(ptr){}
	~Auto_ptr_int() {
		delete ptr;
	}
	// 取值运算
	int operator*() {
		return ptr[0];	// return *ptr
	}
	int*& get() {
		return ptr;
	}
private:
	int* ptr;
};

void test_ptr() {
	Auto_ptr_int p(new int(100));
	cout << *p << endl;
	cout << *(p.get()) << endl;
}
int main() {
	test_my_int();
	test_func();
	test_ptr();
	return 0;
}
C++默认存在的函数
#include
#include
using namespace std;
class YXC {
public:
	YXC() = default;
	~YXC() = default;
	YXC(const YXC& object) = default;
	YXC& operator=(const YXC& object) = default;
	// 1.默认构造函数
	// 2.默认析构函数
	// 3.默认拷贝构造函数
	// 4.默认的赋值重载
	void printYXC() {
		cout << "name:"" << this->name <<""" << "tage:" << this->age;
	}
private:
	string name;
	int age;
};
// 重载中的特殊情况
// 对象加常量的情况
class Test {
public:
	Test(int num) :num(num){}
	void printData() {
		cout << num << endl;
	}
	// 正常人处理方法
	// friend Test operator+(Test test,int data)_
	// {
	//		return Test(test.num + data);
	//	}
	// friend Test operator+(int data,Test test)
	//{
	//	return Test(test.num + data);
	//}
	Test operator+(Test test1) {
		return Test(this->num + test1.num);
	}
private:
	int num;
};

int main() {
	YXC yxc;
	YXC result = yxc;
	YXC temp;
	temp = yxc;
	temp.printYXC();
	Test object(1);
	object.printData();

	// 不正常的重载智能用友元方式,才可以让下面都正确
	// 友元重载解析:operator+(1,object); Test object1=1
	Test res = object + 1; // 友元重载解析: operator+(object,1);
	res.printData();
	// Test res = 1 + object;// 类成员函数重载会报错
	// res2.printData();

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

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

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