当自定义类型需要进行运算的时候必须讲运算符进行重载。运算符重载使得编译器给所有的类起了一个通用的运算符名称即operator和运算符组合的形式,这样不同类在重载运算符的时候就有一个通用的名字了。
加号运算符重载
类和基本内置类型相加的实现:
这种情况可以使用全局函数重载和成员函数重载
1 class Person { 2 public: 3 Person operator+(int num) { 4 Person temp; 5 temp.a_ = this->a_ + num; 6 temp.b_ = this->b_ + num; 7 return temp; 8 } 9 int a_; 10 int b_; 11 }; 12 void test01() { 13 Person p1; 14 p1.a_ = 10; 15 p1.b_ = 10; 16 17 Person p3 = p1 + 10; 18 cout << p3.a_ << endl; 19 }
输出结果是20
左移运算符的重载:
这个时候只能使用全局函数重载,因为我们想要cout在输出对象的前面,总的来说成员函数重载和成员函数的重载的不同之处在于,成员函数重载你不能控制它的顺序比如cout你必须在对象的左侧,而全局函数的重载可以控制顺序,即第一个参数在第二个参数的左侧。
1 class Person { 2 friend std::ostream& operator<<(std::ostream& cout, Person& p); 3 public: 4 Person(int a, int b) :a_(a), b_(b) { 5 6 } 7 private: 8 int a_; 9 int b_; 10 }; 11 std::ostream& operator<<(std::ostream& cout, Person& p) { 12 cout << p.a_ << endl; 13 return cout; 14 } 15 void test01() { 16 Person p(10,20); 17 cout << p << endl; 18 }
当函数返回自定义对象时,想要打印这个函数的返回值,重载第二个参数必须用const
举个不恰当的例子:
struct student { int age ; string name; }; std::ostream& operator<<(std::ostream& cout, const student& st) { cout << st.age << endl; cout << st.name << endl; return cout; } student fun() { student st; st.age = 10; st.name = "张三"; return st; } int main() { cout << fun() << endl; system("Pause"); return 0; }
如果不加const:
这是因为fun()返回的student是个右值,但是重载的<<,第二个参数是个左值引用,fun()无法绑定到左值引用,改成 const student&就可以绑定到右值了。
前置和后置递增运算符(递减也一样的)
1 Myinteger& operator++() { 2 ++num_; 3 return *this; 4 }//前置 5 Myinteger operator++(int) { 6 Myinteger ret = *this; 7 ++num_; 8 return ret; 9 }//后置
下面进行几点说明:
- 后置运算符为什么不返回引用,因为ret是局部对象,不能返回局部对象的引用
- 从这个地方可以看出来为什么前置是左值,而后置是右值;因为前置返回的是一个引用,引用是左值。而后置在函数执行return语句的时候函数会创建一个临时量,这个临时变量会接收ret的值,因为是临时量所以它是右值。从内置类型的角度来看左值和右值:
这里面后置报错的原因就是因为a加加之后是一个右值而右值不可以修改,而前置加加后是一个左值,左值可以更改。
函数调用运算符
1 class Myprint { 2 public: 3 void operator()(string test) { 4 cout << test << endl; 5 } 6 7 }; 8 class Myadd { 9 public: 10 int operator()(int num1, int num2) { 11 return num1 + num2; 12 } 13 }; 14 void test01() { 15 Myprint myprint; 16 myprint("hello world"); //由于使用起来非常像一个函数调用因此称为一个仿函数 17 } 18 void test02() { 19 Myadd myadd; 20 int ret = myadd(100, 100); 21 cout << "ret=" << ret << endl; 22 //匿名函数对象,执行过当前行就被释放 23 cout << Myadd()(100, 100) << endl; 24 } 25 26 int main(){ 27 //仿函数特别灵活,没有固定的写法 28 test01(); 29 test02(); 30 system("pause"); 31 return 0; 32 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!