当前位置: 首页 > news >正文

C++(友元和运算符重载)

目录

友元:

友元函数:

示例:

友元类:

示例:

优点:

注意事项:

运算符重载:

注意:

示例:


友元:

C++中如果想要外部函数或者类对一个类的private(私有成员)和protected(保护成员),可以通过使用friend关键字对其进行声明。

声明位置灵活,可以在类内任何访问区域进行友元声明。

友元函数:

友元函数一般在运算符重载和需要访问私有数据的全局函数进行使用。友元函数是声明在类内的非成员函数,可以访问该类的所有成员(包括私有和保护成员)。

示例:

通过友元函数访问Student类的私有成员_name,在类内声明GetStudentName()友元函数,在类外进行定义来。

#include <iostream>
#include <string>
#include <thread>class Student {friend void GetStudentName(const Student& student);
public:Student():_name(""),_age(0),_data(new int(0)) {std::cout << "无参构造" << std::endl;}Student(std::string name, int age,int number):_name(name),_age(age),_data(new int(number)) {std::cout << "有参构造" << std::endl;}Student(const Student &student):_name(student._name),_age(student._age) {//const可以加可以不加,主要是为了防止对参数进行修改,但是&是必须加std::cout << "拷贝构造" << std::endl;_data = new int();*_data = *student._data;}Student(Student && student):_name(std::move(student._name)),_age(student._age),_thread(std::move(student._thread)){std::cout << "移动构造" << std::endl;_data = new int();*_data = std::move(*(student._data));}~Student() {std::cout << "析构函数" << std::endl;delete _data;}void GetTarget() {std::cout << "获取的target的值:";std::cout << _target << std::endl;std::cout << std::endl;}void ModifyTarget(int target) {std::cout << "修改target之后的值:";_target = target;std::cout << _target<<std::endl;}void GetName() {std::cout << _name << std::endl;}void GetAge() {std::cout << _age << std::endl;}void GetData() {std::cout << _data << std::endl;}
private:std::string _name;int _age;static int _target;//类内声明,类外初始化std::thread _thread;int* _data;
};
int Student::_target = 100;void GetStudentName(const Student& student) {std::cout << student._name << std::endl;
}int main() {Student student1("小明",16,10);GetStudentName(student1);return 0;
}

运行结果:

友元类:

友元类是其所有成员均可以访问另一个类的私有成员和保护成员的类。需要注意的是:

类A声明为类B为友元,不意味着类B自动授予类A的访问权限,类B可以访问类A的私有成员和保护成员,但是类A不是类B的友元,所以不能访问类B的私有成员和保护成员。

如果类B是类A的友元类,同时类C是类B的友元,类C是不会自动成为类A的友元,也就是不会有传递性。

基类的派生类不会继承基类的友元关系,也就是没有继承性。

示例:

创建一个获取Student类的私有成员_name的类,在其成员函数中定义获取的成员函数func()。

#include <iostream>
#include <string>
#include <thread>class Student {friend void GetStudentName(const Student& student);
public:Student():_name(""),_age(0),_data(new int(0)) {std::cout << "无参构造" << std::endl;}Student(std::string name, int age,int number):_name(name),_age(age),_data(new int(number)) {std::cout << "有参构造" << std::endl;}Student(const Student &student):_name(student._name),_age(student._age) {//const可以加可以不加,主要是为了防止对参数进行修改,但是&是必须加std::cout << "拷贝构造" << std::endl;_data = new int();*_data = *student._data;}Student(Student && student):_name(std::move(student._name)),_age(student._age),_thread(std::move(student._thread)){std::cout << "移动构造" << std::endl;_data = new int();_data = std::move(student._data);}~Student() {std::cout << "析构函数" << std::endl;delete _data;}void GetTarget() {std::cout << "获取的target的值:";std::cout << _target << std::endl;std::cout << std::endl;}void ModifyTarget(int target) {std::cout << "修改target之后的值:";_target = target;std::cout << _target<<std::endl;}Student operator+(const Student& other)const {Student temp;temp._age=this->_age + other._age;temp._data = new int(*this->_data + *other._data);return temp;}Student& operator=(const Student& other) {if (this == &other) {return *this;}delete _data;this->_name = other._name;this->_age = other._age;this->_data = new int();*this->_data = *other._data;std::cout << "拷贝赋值运算符" << std::endl;return *this;}Student& operator=(Student&& other)noexcept {if (this == &other) {return *this;}delete this->_data;this->_name = std::move(other._name);this->_age = other._age;this->_data = other._data;other._data = nullptr;std::cout << "移动赋值运算符" << std::endl;return *this;}Student& operator++() {this->_age++;(*this->_data)++;return *this;}const Student operator++(int) {Student temp(*this);this->_age++;(*this->_data)++;return temp;}friend std::ostream& operator<<(std::ostream& os, Student& other);
private:std::string _name;int _age;static int _target;//类内声明,类外初始化std::thread _thread;int* _data;
};
int Student::_target = 100;void GetStudentName(const Student& student) {std::cout << student._name << std::endl;
}std::ostream& operator<<(std::ostream& os, Student& other) {os << other._name << "  "<< other._age << "  "<< *other._data << std::endl;return os;
}int main() {std::cout << "构造student1和student2:" << std::endl;Student student1("小明",16,10);Student student2("小刚", 10, 10);std::cout << student2;std::cout << student1;std::cout << std::endl << "构造student3:" << std::endl;Student student3;student3=student1 + student2;std::cout << student3;std::cout <<std::endl<< "对student1进行前置++,对student2进行后置++:" << std::endl;Student student5=++student1;Student student6=student2++;std::cout << "前置++:" << std::endl;std::cout << student1;std::cout << student5;std::cout << "后置++:" << std::endl;std::cout << student2;std::cout << student6;std::cout << "移动赋值运算符:" << std::endl;Student student7;student7=std::move(student2);std::cout << student7;return 0;
}

运行结果:

优点:

避免了共有接口简介访问私有数据,支持特殊的场景,比如运算符重载等。

注意事项:

友元会破坏类的封装性,不能够通过继承或者嵌套自动传递,会导致代码的耦合度增加,维护难度上升。

优先使用成员函数或者公有接口,在必要时使用友元,尽量使用友元函数不使用友元类,减少权限的开放。

运算符重载:

通过成员函数或者友元函数重新定义运算符对自定义类型的操作行为。

注意:

运算符重载不能够创建新的运算符。

不能够改变运算符的优先级和结合性。

并非所有的运算符都能够进行重载,比如成员当问运算符、成员指针运算符、作用域解析运算符、条件运算符、sizeof和typeid运算符不能够进行重载。

示例:

对"+"、"<<"、"="、"前置++"、"后置++"进行重载。"-"、"*"、和"/"和"+"是一样的思路。注意区分前置++和后置++的区别,还需要注意重载时,前置++和后置++的函数参数区别。移动语义操作中一定注意将被移动对象的指针置空,防止出现双重释放或者悬空指针问题。

#include <iostream>
#include <string>
#include <thread>class Student {friend void GetStudentName(const Student& student);
public:Student():_name(""),_age(0),_data(new int(0)) {std::cout << "无参构造" << std::endl;}Student(std::string name, int age,int number):_name(name),_age(age),_data(new int(number)) {std::cout << "有参构造" << std::endl;}Student(const Student &student):_name(student._name),_age(student._age) {//const可以加可以不加,主要是为了防止对参数进行修改,但是&是必须加std::cout << "拷贝构造" << std::endl;_data = new int();*_data = *student._data;}Student(Student && student):_name(std::move(student._name)),_age(student._age),_thread(std::move(student._thread)){std::cout << "移动构造" << std::endl;_data = new int();_data = std::move(student._data);}~Student() {std::cout << "析构函数" << std::endl;delete _data;}void GetTarget() {std::cout << "获取的target的值:";std::cout << _target << std::endl;std::cout << std::endl;}void ModifyTarget(int target) {std::cout << "修改target之后的值:";_target = target;std::cout << _target<<std::endl;}Student operator+(const Student& other)const {Student temp;temp._age=this->_age + other._age;temp._data = new int(*this->_data + *other._data);return temp;}Student& operator=(const Student& other) {if (this == &other) {return *this;}delete _data;this->_name = other._name;this->_age = other._age;this->_data = new int();*this->_data = *other._data;std::cout << "拷贝赋值运算符" << std::endl;return *this;}Student& operator=(Student&& other)noexcept {if (this == &other) {return *this;}delete this->_data;this->_name = std::move(other._name);this->_age = other._age;this->_data = other._data;other._data = nullptr;std::cout << "移动赋值运算符" << std::endl;return *this;}Student& operator++() {this->_age++;(*this->_data)++;return *this;}const Student operator++(int) {Student temp(*this);this->_age++;(*this->_data)++;return temp;}friend std::ostream& operator<<(std::ostream& os, Student& other);
private:std::string _name;int _age;static int _target;//类内声明,类外初始化std::thread _thread;int* _data;
};
int Student::_target = 100;void GetStudentName(const Student& student) {std::cout << student._name << std::endl;
}std::ostream& operator<<(std::ostream& os, Student& other) {os << other._name << "  "<< other._age << "  "<< *other._data << std::endl;return os;
}int main() {std::cout << "构造student1和student2:" << std::endl;Student student1("小明",16,10);Student student2("小刚", 10, 10);std::cout << student2;std::cout << student1;std::cout << std::endl << "构造student3:" << std::endl;Student student3;student3=student1 + student2;std::cout << student3;std::cout <<std::endl<< "对student1进行前置++,对student2进行后置++:" << std::endl;Student student5=++student1;Student student6=student2++;std::cout << "前置++:" << std::endl;std::cout << student1;std::cout << student5;std::cout << "后置++:" << std::endl;std::cout << student2;std::cout << student6;std::cout << "移动赋值运算符:" << std::endl;Student student7;student7=std::move(student2);std::cout << student7;return 0;
}

运行结果:


文章转载自:

http://vf0HDL2z.grbdr.cn
http://W2TT93L8.grbdr.cn
http://9TQFHvOZ.grbdr.cn
http://g6TQAoJ1.grbdr.cn
http://4ErqV32k.grbdr.cn
http://FngKmv6V.grbdr.cn
http://ypsZmiGm.grbdr.cn
http://X9odSiHJ.grbdr.cn
http://lfnz0FRg.grbdr.cn
http://CB13zyqP.grbdr.cn
http://AcfnDh3S.grbdr.cn
http://LE3FwzUx.grbdr.cn
http://Yp3rUhYf.grbdr.cn
http://j9E6PaoK.grbdr.cn
http://mjAxUR6n.grbdr.cn
http://k7sy6iH7.grbdr.cn
http://DeETQ89R.grbdr.cn
http://xPFR3quE.grbdr.cn
http://JcJJilSl.grbdr.cn
http://MFzem7mX.grbdr.cn
http://gRr9QW5L.grbdr.cn
http://hLZmeaWL.grbdr.cn
http://1C9AjgUz.grbdr.cn
http://NrqA86PG.grbdr.cn
http://Etl3OvkA.grbdr.cn
http://U3UCZYk4.grbdr.cn
http://MpE4iiRc.grbdr.cn
http://9dJDCZcp.grbdr.cn
http://sqmOIlIv.grbdr.cn
http://qYD2ryux.grbdr.cn
http://www.dtcms.com/a/379710.html

相关文章:

  • SpringBoot4与Spring7发布:云原生深度进化
  • k8s查询ServiceAccount有没有列出 nodes 的权限
  • C++ list的模拟实现
  • FreeRTOS任务切换核心机制揭秘
  • OpenCV 指纹验证、识别
  • LeetCode 刷题【73. 矩阵置零】
  • Ubuntu 系统安装 Miniconda 完整方法与注意事项
  • 计算机视觉(opencv)实战十七——图像直方图均衡化
  • vue3 样式 css、less、scss、sass 的说明
  • CSS 中 white-space 用于控制元素内空白符(空格、制表符、换行符)的处理方式以及文本的换行行为
  • 少儿舞蹈小程序(14)在线预约
  • 【uniapp微信小程序】扫普通链接二维码打开小程序
  • 基于uni-app的蛋糕订购小程序的设计与实现(代码+数据库+LW)
  • 微服务保护和分布式事务
  • 线性代数 · 行列式 | Sarrus Rules / Laplace Expansion
  • uni小程序中使用Echarts图表
  • 小程序setNavigationBarColor设置背景渐变,图片渐变
  • OpenAI与微软“再造合作”:重组背后的资本与生态博弈
  • IP验证概述
  • 【RabbitMQ】高级特性:持久性·发送方确认·重试机制·TTL·死信队列·延迟队列·事务·消息分发
  • Cherry Studio递归工具调用机制深度解析
  • python+springboot大学生心理测评与分析系统 心理问卷测试 自动评分分析 可视化反馈系统
  • 多模态大模型1:Crab
  • MySQL 面试场景题之如何处理 BLOB 和CLOB 数据类型?
  • Python 数据分析:从新手到高手的“摸鱼”指南
  • 手写Spring底层机制的实现【初始化IOC容器+依赖注入+BeanPostProcesson机制+AOP】
  • 【MySQL】表的操作和数据类型
  • QT M/V架构开发实战:QFileSystemModel介绍
  • 基于POI-TL实现动态Word模板的数据填充:【散点图】特殊处理方案
  • Chrome插件开发入门技术文章大纲