第十一站:运算符重载operate(+-*/)

目录

 使用成员函数重载运算符

 使用非成员函数重载运算符

 使用重载函数运算整数

禁区: 

 赋值重载运算符=

bug:

 关系重载运算符><

下标运算符重载

 bug

输入输出运算符重载<<,>>

使用成员函数

使用友元函数 (更方便)

 普通类型==>类类型

 类类型==>普通类型

类类型转换成类类型(拷贝)


operate(+,-,*,/,=,->,<<,>>)支持使用友元函数

(),=,->,[]不支持使用友元函数

局限:C/C++的运算符,支持的数据类型,仅限于基本数据类型

 使用成员函数重载运算符

 //一只牛+一只羊
Pig operator+(const Goat& goat);//一个参数是本类,一个是goat类,返回值是pig类
//一只牛+一只牛
Pig operator+(const Cow& cow);

//相当于将值返回给猪,牛.operate+(羊)
Pig Cow::operator+(const Goat& goat){
    int tmp = this->weight * 2 + goat.getWeight() * 3;
    return Pig(tmp);
}
Pig Cow::operator+(const Cow& cow) {
    int tmp = (this->weight + cow.weight) * 2;
    return Pig(tmp);
}

    cout << "牛牛相加得:";
    Cow h1(100);
    Cow h2(200);
    Pig p1 = h1+h2;

    cout << p1.describe() << endl;

  使用非成员函数重载运算符

 friend Pig operator+(const Cow& cow, const Goat& goat);
friend Pig operator+(const Cow& cow, const Cow& cow1);

Pig operator+(const Cow& cow, const Goat& goat) {
    int tmp = cow.weight * 2 + goat.getWeight()*3;
    return tmp;
}

Pig operator+(const Cow& cow , const Cow& cow1) {
    int tmp = cow.weight * 2 + cow1.weight * 2;
    return tmp;
}

cout << "牛牛相加得:";
Cow h1(100);
Cow h2(200);
Pig p1 = operator+(h1,h2);
cout << p1.describe() << endl;

 使用重载函数运算整数

Pig operator+(int n);//一个参数是本身,一个是整数n,,返回值是pig类

禁区: 

不能对标准运算符进行重载:1+1=2

不能改变原运算符的语法规则,单目运算符不能变为双目运算符

不能改变运算符的优先级

不能创造新的运算符(错:operator**)

(),=,->,[]不支持使用友元函数 

 赋值重载运算符=

.h 

#pragma once
#include <string>
#include <iostream>
using namespace std;
class Boy{
public:
	Boy(const char* name=NULL, int age=0, int salary=0, int darkHorse=0);
	Boy& operator=(const Boy& boy);
	~Boy();

    string decribe();
private:
	char* name;
	int age;
	int salary;
	int darkHorse;
	unsigned int id;
	static int LAST_ID;
};

 .cpp

#include "Boy.h"
#include <string>
#include <sstream>
int Boy::LAST_ID = 0;//编号初始化为0

Boy::Boy(const char* name, int age, int salary, int darkHorse){
	if (!name){
		name = "未知";
	}
	this->name = new char[strlen(name) + 1];
	strcpy_s(this->name, strlen(name) + 1, name);
	this->age = age;
	this->salary = salary;
	this->darkHorse = darkHorse;
	this->id = ++LAST_ID;
}

Boy& Boy::operator=(const Boy& boy){
	if (!name){
		delete name;
	}
	this->name = new char[strlen(name) + 1];
	strcpy_s(this->name, strlen(name) + 1, boy.name);
	this->age = boy.age;
	this->salary = boy.salary;
	this->darkHorse = boy.darkHorse;
	return *this;
}

Boy::~Boy()
{
	if (!name)
	{
		delete name;
	}
}

string Boy::decribe(){
	stringstream ret;
	ret << "编号:" << id << "\t姓名:" << name << "\t年龄:" << age
		<< "\t薪资:" << salary << "\t黑马值:" << darkHorse << endl;
	return ret.str();
}

bug:

使用指针是无法达到赋值运算符的重载的,这时候使用赋值运算重载,是编译器默认的合成赋值重载------->以下代码纯粹无效

Boy& operator=(const Boy* boy);

//h2 = h1

//h2.operator(h1)//Boy boy = h1//这里会调用合成的拷贝构造函数,严重出错

有两个影响:
1) 浪费性能
2) 如果没有自定义的拷贝构造函数,而且这个类又有指针成员时,就会调用自动生成的拷贝构
造函数,导致浅拷贝
如果析构函数中,对这个指针指向的内存做了释放,那就导致数据损坏或崩溃

Boy& Boy::operator=(const Boy boy);

Boy& Boy::operator=(const Boy& boy);//正确

Boy& Boy::operator=(const Boy* boy){
    if (!name){
        delete name;
    }
    this->name = new char[strlen(boy->name) + 1];
    strcpy_s(this->name, strlen(boy->name) + 1, boy->name);
    this->age = boy->age;
    this->salary = boy->salary;
    this->darkHorse = boy->darkHorse;
    this->id = ++LAST_ID;//id有问题
    return *this;
}

主函数.cpp

#include "Boy.h"
#include <iostream>

using namespace std;

int main(void) {
	Boy h1("Rock", 23, 42000, 10);
	Boy h2, h3;
	h3 = h2 = h1;
	cout << h1.decribe() << endl;
	cout << h2.decribe() << endl;
	cout << h3.decribe() << endl;

	return 0;
}

 关系重载运算符><

bool operator<(const Boy& boy);
bool operator>(const Boy& boy);

int power() const;

bool Boy::operator>(const Boy& boy) {
    if (this->power() > boy.power()) {
        return true;
    }
    else {
        return false;
    }
}
int Boy::power() const{
     薪资* 黑马系数 + (100 - 年龄) * 1000
    int power = salary * darkHorse + (100 - age) * 1000;
    return power;
}
 

cout << "比较的结果" << endl;
if (h1<h2) {
    cout << h2.decribe() << endl;
}else{
    cout << h1.decribe() << endl;

下标运算符重载

 

#pragma once
#include <string>
#include <iostream>
using namespace std;

#define NAME_key "name"
#define AGE_key "age"
#define SALARY_key "salary"
#define DARKH_key "darkHorse"
#define Power_key "power"

enum MyEnum
{
	AGE, //"age"
	SALARY, //"salary"
	DARKH, //"darkHorse"
	Power //"power"
};
class Boy{
public:
	Boy(const char* name=NULL, int age=0, int salary=0, int darkHorse=0);
	Boy& operator=(const Boy& boy);
	~Boy();
	/*bool operator<(const Boy& boy);
	bool operator>(const Boy& boy);*/
	int operator[](string name);
	int operator[](int index);
	int power() const;
    string decribe();
private:
	char* name;
	int age;
	int salary;
	int darkHorse;
	unsigned int id;
	static int LAST_ID;
};

.cpp

int Boy::operator[](string name){
	if (name == AGE_key){
		return age;
	}
	else if (name == SALARY_key) {
		return salary;
	}
	else if (name == DARKH_key) {
		return darkHorse;
	}
	else if (name == Power_key) {
		return power();
	}
	else {
		return -1;
	}
}

int Boy::operator[](int index) {
	if (index == 0) {
		return age;
	}
	else if (index == 1) {
		return salary;
	}
	else if (index == 2) {
		return darkHorse;
	}
	else if (index == 3) {
		return power();
	}
	else {
		return -1;
	}
}


Boy h1("Rock", 23, 42000, 10);
Boy h2("Jack", 30, 40000, 5);

cout << "年龄:" << h1[AGE_key] 
 << "\t\t薪资:" << h1[SALARY_key] 
 << "\t\t黑马值:" << h1[DARKH_key] 
 << "\t\t综合能力值:" << h1[Power_key] << endl;

cout << "年龄:" << h1[AGE]
    << "\t\t薪资:" << h1[SALARY]
    << "\t\t黑马值:" << h1[DARKH]
    << "\t\t综合能力值:" << h1[Power] << endl;

 bug

下标运算符重载使用const时,要注意

int operator[](string name)const;
int operator[](int index);

const Boy h1;

cout<<h1[1];//这种的话他是不会调用参数为整数的下标重载运算符的

因为const只能调用const方法

输入输出运算符重载<<,>>

使用成员函数

ostream& operator<<(ostream& os) const;

ostream& Boy::operator<<(ostream& os) const
{
    os << "编号:" << id << "\t姓名:" << name << "\t年龄:" << age
        << "\t薪资:" << salary << "\t黑马值:" << darkHorse;
    return os;
}

h1<<cout;

使用友元函数 (更方便)

friend ostream& operator<<(ostream& os, const Boy& boy);

ostream& operator<<(ostream &os,const Boy &boy) {
    os << "编号:" << boy.id << "\t姓名:" << boy.name << "\t年龄:" << boy.age
        << "\t薪资:" << boy.salary << "\t黑马值:" << boy.darkHorse;
    return os;
}

istream& operator>>(istream& is, Boy& boy) {
    string name1;
    is >> name1 >> boy.age >> boy.salary >> boy.darkHorse;
    boy.name = new char[sizeof(name1)];
    strcpy_s(boy.name, sizeof(name1), name1.c_str());

    return is;
}

Boy h1("Rock", 23, 42000, 10);
Boy h2("Jack", 30, 40000, 5);
cout << h1 << endl << h2 << endl;
cout << "请输入:" << endl;
cin >> h1;
h1 << cout;

 普通类型==>类类型

boy.h
//普通类型转类类型,使用构造函数
Boy(int salary);
Boy(const char* name);

BOY.cpp
Boy::Boy(int salary){
	const char* name1 = "未命名的";
	name = new char[strlen(name1) + 1];
	strcpy_s(this->name, strlen(name1) + 1, name1);
	this->age = 0;
	this->salary = salary;
	this->darkHorse = 0;
	this->id = ++LAST_ID;
}
Boy::Boy(const char* name) {
	this->name = new char[strlen(name) + 1];
	strcpy_s(this->name, strlen(name) + 1, name);
	this->age = 0;
	this->salary = 0;
	this->darkHorse = 0;
	this->id = ++LAST_ID;
}
main.cpp
Boy h1("Rock", 23, 42000, 10);
Boy h2("Jack", 30, 40000, 5);
//普通类型转类类型(构造函数)
h1 = 20000; // h1(2000);
cout << h1 << endl;

h2 = "Martin";//h2("Martin");
cout << h2 << endl;

  类类型==>普通类型

 

boy.h
//将类类型转换成普通类型
operator int()const;
operator char* ()const;

boy.cpp
Boy::operator int() const{
	return salary;
}
Boy::operator char* ()const {
	return this->name;
}
main.cpp
Boy h1("Rock", 23, 42000, 10);
Boy h2("Jack", 30, 40000, 5);
//将类型转成普通类型(operator 数据类型())
int salary = h1;
cout << "薪资:" << salary << endl;;
char *name = h2;
cout <<"姓名"<< name;

类类型转换成类类型

Boy.h

friend class MAN;

MAN.h
#pragma once
#include <iostream>
using namespace std;
class Boy;

class MAN{
public:
	MAN(const char* name, int age, int salary);
	~MAN();
	MAN(const Boy& boy1);

private:
	char* name;
	int age;
	int salary;
	static int id;
	friend ostream& operator<<(ostream& os, const MAN& man);
};
ostream& operator<<(ostream& os, const MAN& man);


MAN.cpp

#include "MAN.h"
#include "Boy.h"
int MAN::id = 0;
MAN::MAN(const char* name, int age, int salary)
{
	this->name = new char(strlen(name) + 1);
	strcpy_s(this->name, strlen(name) + 1, name);
	this->age = age;
	this->salary = salary;
	this->id = ++id;
}

MAN::~MAN(){
	delete name;
}

MAN ::MAN(const Boy& boy1){
	/*this->name = new char(strlen(boy1.name) + 1);
	strcpy_s(this->name, strlen(name) + 1, boy1.name);*/
	int len = strlen(boy1) + 1;
	this->name = new char[(char)len];
	strcpy_s(name, (char)len, (char*)boy1);
    	/*
	int operator[](string name)const;
	int operator[](int index) const;
	*/
	//这里使用下标调用是需要注意,引用的Boy为const类型
	//所有对应下标运算符重载也要为const类型
	//this->age = boy1[AGE];
	//this->salary = boy1[SALARY];
	this->age = boy1.age;
	this->salary = boy1.salary;
	this->id = boy1.id;
}

ostream& operator<<(ostream& os, const MAN& man)
{
	os << "编号:" << man.id << "\t姓名:" << man.name << "\t年龄:"
		<< man.age << "\t薪资:" << man.salary << endl;
	return os;
}
main.cpp

MAN man = h1;
cout << h1 << endl;
cout << man << endl;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/335053.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV-Python(48):K均值聚类

目标 学习K值聚类的概念以及工作原理。K均值聚类的OpenCV实现 背景 下面用一个最常用的例子来给大家介绍K 值聚类。 话说有一个公司要生产一批新的T 恤。很明显他们要生产不同大小的T 恤来满足不同客客的要求。所以这个公司搜集了很多人的身高和体重信息&#xff0c;并把这些…

【C语言】编译和链接深度剖析

文章目录 &#x1f4dd;前言&#x1f320; 翻译环境和运行环境&#x1f309;翻译环境 &#x1f320;预处理&#xff08;预编译&#xff09;&#x1f309;编译 &#x1f320;词法分析&#x1f320;语法分析 &#x1f309;语义分析&#x1f320;汇编 &#x1f309; 链接&#x1f…

23号资源——电力系统程序集合已提供下载资源

23号资源&#xff1a;程序集合包含9个程序&#xff08;经典电力系统经济调度程序&#xff1b;2解决带储&#xff1b;3智能微电网PSO优化算法&#xff1b;微电网调度等等&#xff0c;见资源描述&#xff09;资源-CSDN文库https://download.csdn.net/download/LIANG674027206/887…

C++继承(万字详!!)

文章目录 继承的概念及定义继承的概念继承定义 基类和派生类对象赋值转换继承中的作用域派生类的默认成员函数继承与友元继承与静态成员复杂的菱形继承及菱形虚拟继承菱形继承菱形虚拟继承 继承的总结和反思笔试面试题 继承的概念及定义 继承的概念 继承(inheritance) 机制是面…

【Docker】实战多阶段构建 Laravel 镜像

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; 本节适用于 PHP 开发者阅读。Laravel 基于 8.x 版本&#xff0c;各个版本的文件结构可能会有差异&#xff0c;请根据实际自行修改。 准备 新…

开源模型应用落地-qwen模型小试-入门篇(五)

一、前言 这是关于qwen模型入门的最后一篇文章。主要介绍如何使用魔搭的API在本地调用qwen模型。此外&#xff0c;通过阅读这一系列的文章&#xff0c;如果您真的亲自动手实践过&#xff0c;我相信您已经掌握了qwen模型的基本使用方法。 二、术语 2.1. ModelScope社区 打造下一…

HCIA—— 16每日一讲:HTTP和HTTPS、无状态和cookie、持久连接和管线化、(初稿丢了,这是新稿,请宽恕我)

学习目标&#xff1a; HTTP和HTTPS、无状态和cookie、持久连接和管线化、HTTP的报文、URI和URL&#xff08;初稿丢了&#xff0c;这是新稿&#xff0c;请宽恕我&#x1f636;‍&#x1f32b;️&#xff09; 学习内容&#xff1a; HTTP无状态和cookieHTTPS持久连接和管线化 目…

流量控制与熔断利器:Sentinel介绍

这是《百图解码支付系统设计与实现》专栏系列文章中的第&#xff08;19&#xff09;篇&#xff0c;也是流量控制系列的第&#xff08;6&#xff09;篇。点击上方关注&#xff0c;深入了解支付系统的方方面面。 本篇聊聊流量控制与熔断利器Sentinel&#xff0c;背后的原理&…

分享行政检察院法律监督模型的构建价值和运用范式

数字检察是检察工作现代化的重要依托。在数字化时代背景下&#xff0c;行政检察监督办案要深入推进检察大数据战略&#xff0c;推动办案模式从“个案为主、数量驱动”向“类案为主、数据赋能”转变&#xff0c;通过数据分析、数据碰撞、数据挖掘发现治理漏洞或者监督线索&#…

项目上线存在的缓存问题以及存在的debugger和console.log等问题

下载uglifyjs-webpack-plugin插件 在vue.config文件中进行配置 publicPath: process.env.NODE_ENV production ? ./ : /,outputDir: n-sim-ipc-manage-build,productionSourceMap: false,configureWebpack: config > {//打包文件增加hashconfig.output.filename js/[nam…

大模型日报-20240120

这里写目录标题 视觉Mamba来了&#xff1a;速度提升2.8倍&#xff0c;内存能省87%一键实景转动画&#xff0c;清华系初创公司全球首发4D骨骼动画框架&#xff0c;还能生成个性化角色如何利用革命性的蛋白质结构工具来发现药物&#xff1f;AlphaFold 发现了数千种可能的致幻剂扎…

IPFoxy运营干货|谷歌广告Google Ads建立广告需要注意什么?

编辑投放谷歌广告需要多少个步骤和什么准备工作&#xff0c;本文将来讲述&#xff0c;主要分5个内容&#xff1a;一、投放前竞对研究&#xff1b;二、投放前广告账户设置&#xff1b;三、建立广告系列&#xff1b;四、建立广告组&#xff1b;五、广告长期策略。接下来我们来开始…

Python 面向对象绘图(Matplotlib篇-16)

Python 面向对象绘图(Matplotlib篇-16)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

链表存数相加算法(leetcode第2题)

题目描述&#xff1a; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外&#xff0c;这…

无偿分享一个很有用的看源码小技巧

怎么在 idea 里面查看 git 提交记录呢&#xff1f;这个界面是藏在哪里的呢&#xff0c;我的 idea 里面怎么没有呢&#xff1f; 好的&#xff0c;是我疏忽了&#xff0c;我先入为主的认为这个大家应该都知道是怎么来的。 但是确实是有一些同学是不太清楚的&#xff0c;那我这篇…

大数据导论(2)---大数据与云计算、物联网、人工智能

文章目录 1. 云计算1.1 云计算概念1.2 云计算的服务模式和类型1.3 云计算的数据中心与应用 2. 物联网2.1 物联网的概念和关键技术2.2 物联网的应用和产业2.3 大数据与云计算、物联网的关系 1. 云计算 1.1 云计算概念 1. 首先从商业角度给云计算下一个定义&#xff1a;通过网络…

C#调用C++ dll异常排查

基本情况 最近在做的一款程序&#xff0c;长时间运行总会出现莫名的问题。有时是自动关闭&#xff0c;有时程序报错&#xff0c;有时调用的dll异常…… 提出假设——dll内存泄漏 由于开始与C组合作时&#xff0c;使用其提供的dll出现过数据读写时异常&#xff08;内存操作异常…

Leetcoder Day9|栈与队列part01

语言&#xff1a;Java/C 目录 理论基础 C 栈 队列 Java 栈 队列 ​编辑 232.用栈实现队列 225. 用队列实现栈 Queue Deque 今日心得 理论基础 又是考研时数据结构里接触到的老朋友&#xff0c;栈是先进后出&#xff0c;队列是先进先出。 C 现在刷题除了思路还…

CHAPTER 11: 《DESIGN A NEWS FEED SYSTEM》 第 11 章:《设计新闻系统》

在本章中&#xff0c;您将被要求设计一个新闻提要系统。什幺是新闻系统&#xff1f;根据Facebook 页面&#xff0c;“News feed 是中间不断更新的故事列表。您的主页。动态消息包括状态更新、照片、视频、链接、应用活动记录和喜欢您在 Facebook 上关注的人、页面和群组“[1]。…

linux C语言socket函数send

在Linux中&#xff0c;使用C语言进行网络编程时&#xff0c;send函数是用于发送数据到已连接的套接字的重要函数之一。它通常用于TCP连接&#xff0c;但也可以用于UDP&#xff08;尽管对于UDP&#xff0c;通常更推荐使用sendto&#xff0c;因为它允许你指定目标地址和端口&…