目录
1.成员函数运算符重载
2.非成员函数【友元函数】运算符重载
3.运算符重载的禁区与规则
成员函数与非成员函数重载区别
区别:
两种方式选择:
特殊情况
4.运算符重载的禁区和规则
1.成员函数运算符重载
需求:
// 规则:
// 一斤牛肉:2斤猪肉
// 一斤羊肉:3斤猪肉
Cow.h
#pragma once
class Pork;
class Goat;
class Cow{
public:
Cow(int weight=0);
Pork operator+(const Goat&goat);
Pork operator+(const Cow& cow);
private:
int weight;
};
Cow.cpp
#include "Cow.h"
#include"Goat.h"
#include"Pork.h"
Cow::Cow(int weight) {
this->weight = weight;
}
Pork Cow::operator+(const Goat& goat) {
int temp = this->weight*2 + goat.GetWeight() * 3;
return Pork(temp);
}
Pork Cow::operator+(const Cow& cow) {
int temp = (this->weight + cow.weight) * 2;
return Pork(temp);
}
Goat.h
#pragma once
class Goat
{
public:
Goat(int weight = 0);
int GetWeight ()const;
private:
int weight;
};
Goat.cpp
#include "Goat.h"
Goat::Goat(int weight) {
this->weight = weight;
}
int Goat::GetWeight() const {
return weight;
}
Pork.h
#pragma once
#include<string>
class Pork
{
public:
Pork(int weight = 0);
std::string descriWeight();
private:
int weight;
};
Pork.cpp
#include "Pork.h"
#include<sstream>
Pork::Pork(int weight) {
this->weight = weight;
}
std::string Pork::descriWeight() {
std::stringstream ret;
ret << this->weight << "斤猪肉";
return ret.str();
}
main.cpp
#include"Cow.h"
#include"Goat.h"
#include"Pork.h"
#include<iostream>
int main() {
Cow cow1(2000);
Cow cow2(1800);
Goat goat(1000);
Pork pork1 = cow1 + goat;
Pork pork2 = cow1 + cow2;
std::cout << "一只牛+一只羊为:\t";
std::cout << pork1.descriWeight() << std::endl;
std::cout << "两只牛为:\t";
std::cout << pork2.descriWeight() << std::endl;
system("pause");
return 0;
}
运行结果:
![](https://img-blog.csdnimg.cn/bd5a66e1fffb474bbf5dbc711dbaab58.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5ZyG5LmW5ZyG,size_20,color_FFFFFF,t_70,g_se,x_16)
2.非成员函数【友元函数】运算符重载
Cow.h
#pragma once
class Pork;
class Goat;
class Cow{
public:
Cow(int weight=0);
friend Pork operator+(const Cow & cow ,const Goat&goat);
friend Pork operator+(const Cow& cow1, const Cow& cow2);
private:
int weight;
};
Goat.h
#pragma once
class Cow;
class Pork;
class Goat{
public:
Goat(int weight = 0);
friend Pork operator+(const Cow& cow, const Goat& goat);
private:
int weight;
};
main.cpp
#include"Cow.h"
#include"Goat.h"
#include"Pork.h"
#include<iostream>
Pork operator+(const Cow& cow, const Goat& goat) {
int temp = cow.weight * 2 + goat.weight * 3;
return Pork(temp);
}
Pork operator+(const Cow& cow1, const Cow& cow2) {
int temp = cow1.weight * 2 + cow2.weight * 2;
return Pork(temp);
}
int main() {
Cow cow1(2000);
Cow cow2(1800);
Goat goat(1000);
Pork pork1 = cow1 + goat;
//当写 p=g+c,编译器会先找g.operator如果找不到,则寻找operator(g1,c1),如果两个都找到,编译
//器会不知道调用哪个(不能同时使用两种方式重载,会出现二义性)
Pork pork2 = cow1 + cow2;
std::cout << "一只牛+一只羊为:\t";
std::cout << pork1.descriWeight() << std::endl;
std::cout << "两只牛为:\t";
std::cout << pork2.descriWeight() << std::endl;
system("pause");
return 0;
}
运行结果:
![](https://img-blog.csdnimg.cn/6fb9b1bb82bc4b8086b1a3c98fddd66f.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5ZyG5LmW5ZyG,size_20,color_FFFFFF,t_70,g_se,x_16)
3.运算符重载的禁区与规则
成员函数与非成员函数重载区别
区别:
使用成员函数来实现运算符重载时,少写一个参数,因为第一个参数就是this指针
两种方式选择:
1.一般情况下,单目运算符(运算只需一个参数/对象),使用成员函数进行重载更方便
2.一般情况,双木运算符重载,使用友元函数更直观
方便实现a+b和b+a的相同效果,成员函数方式无法实现
例如 cow +100 :=cow.operator(100) 友元函数和成员函数都能实现
而100+cow 只能用友元函数实现
"+"法运算符重载只能有两个参数,成员函数重载时已经默认一个参数为this
特殊情况
(1) = () [ ] -> 不能重载为类的友元函数!!(否则可能和 C++的其他规则矛盾)只能使用成员函数形式进行重载
(2)如果运算符的第一个操作数要求使用隐式类型转换,则必须为友元函数(成员函数方式的第一个参数为this指针)
4.运算符重载的禁区和规则
1. 为了防止对标准类型进行运算符重载,
C++规定重载运算符的操作对象至少有一个不是标准类型,而是用户自定义的类型
比如不能重载 1+2
但是可以重载 cow + 2 和 2 + cow // cow是自定义的对象
2.不能改变原运算符的语法规则, 比如不能把双目运算符重载为单目运算
3.不能改变原运算符的优先级
4.不能创建新的运算符,比如 operator**就是非法的, operator*是可以的
5.不能对以下这四种运算符,使用友元函数进行重载
= 赋值运算符,()函数调用运算符,[ ]下标运算符,->通过指针访问类成员
6. 不能对禁止重载的运算符进行重载
不能被重载的运算符
成员访问 |
. |
域运算 |
:: |
内存长度运算 |
sizeof |
三目运算 |
? : : |
预处理 |
# |
可以被重载的运算符
双目运算符 |
+ - * / % |
关系运算符 |
== != < <= > >= |
逻辑运算符 |
&& || ! |
单目运算符 |
+(正号) -(负号) *(指针) &(取地址) ++ -- |
位运算 |
& | ~ ^ <<(左移) >>(右移) |
赋值运算符 |
= += -= *= /= %= &= |= ^= <<= >>= |
内存分配 |
new delete new[ ] delete[ ] |
其他 |
( ) 函数调用 -> 成员访问 [ ] 下标 , 逗号 |