本片博客是作者在学习c++的过程中的笔记记录,希望和各位读者一起学习交流
运算符重载
- 概念
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型 - 基础
- 运算符函数是一种特殊的成员函数或者友元函数
- 成员函数的语法形式:
类型 类名::operator op(参数表)
{
//操作
} - 一个运算符被重载后,原有的意义没有失去,只是定义了相对特定类的一个新运算符
- 例如:
- //全局函数 完成 + 操作符 重载
Complex operator+(Complex &c1,Complex &c2); - //类成员函数 完成 - 操作符 重载
Complex operator-(Compelx &c2);
- //全局函数 完成 + 操作符 重载
- 本质
运算符重载的本质是函数调用 - 用成员函数或友元函数重载运算符
- 二元运算符
ObjectL op ObjectR
重载为成员函数,解释为:
ObjectL.operator op(ObjectR)
左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递
重载为友元函数,解释为:
operator op(ObjectL,ObjectR)
左右操作数都由参数传递 - 一元运算符
Object op 或 op Object
重载为成员函数,解释为:
Object.operator op()
操作数由对象Object通过this指针隐含传递
重载为友元函数,解释为:
operator op(Object)
操作数由参数表Object提供
eg:重载前置++、后置++运算符- 重载前置++:
成员函数的重载: 函数类型& operator++()
友元函数的重载:friend 函数类型& operator++(类型& ) - 后置++运算符的重载方式:
成员函数的重载:函数类型 operator++(int)
友元函数的重载:friend 函数类型 operator++(类型&, int)
- 重载前置++:
- 二元运算符
注意:重载后置++的返回的是右值,因此返回类型不能加引用
上述程序是重载后置++而且是返回对象的引用,会引用程序宕机,因为tmp是一个临时变量,当后置++运算结束后,tmp就会消失,因此必须返回一个对象,也即会返回一个匿名对象。
-
利用友元函数重载输入、输出流(函数返回值充当左值,需要返回一个引用)
- 基础知识:
- istream和ostream是c++预定义流类
- cin是istream的对象,cout是ostream的对象
- 运算符<<由ostream重载为插入操作,用于输出基本类型数据
- 运算符>>由istream重载为提取操作符,用于输入基本类型数据
- 输出流
函数原型:
friend ostream & operator<<(ostream &out,Test &test)
函数定义:
ostream & operator<<(ostream &out,Test &test)
{
out << test.a << endl;
return out;
} - 输入流
函数原型:
friend istream & operator>>(istream &in,Test &test)
函数定义:
istream & operator>>(istream &in,Test &test)
{
in>>test.a;
return in;
} - c++中不能用友元函数重载的运算符:=、()、[]、->
- 基础知识:
-
重载操作符“=”解决赋值浅拷贝问题
要点:- 先释放内存
- 返回一个引用
- =操作符,结合顺序是从右向左
-
重载运算符[]
函数原型:
int & operator[](int i);
类型 类::operator[](类型); -
重载运算符()
函数原型:
double operator()(double x,double y);
类型 类::operator()(表达式); -
&&、||运算符
这两个运算符不进行重载,因为运算符重载是经过函数调用,但是不可以实现&&、||本身的短路原则 -
重载string案例(案例来自于C++ Primer Plus 第6版 P442)
string.h#pragma once #include<iostream> using std::ostream; using std::istream; class MyString { private: char *str; int len; public: static const int CINLIM = 80; MyString(const char *); MyString(); MyString(const MyString &); ~MyString(); MyString & operator=(const MyString ); MyString & operator=(const char *); char & operator[](int i); const char & operator[](int i) const; friend bool operator<(const MyString &st1, const MyString &st2); friend bool operator>(const MyString &st1, const MyString &st2); friend bool operator==(const MyString &st1, const MyString &st2); friend ostream & operator<<(ostream & os, const MyString &st); friend istream & operator>>(istream & is, const MyString &st); };
string.cpp
#define _CRT_SECURE_NO_WARNINGS #include "string.h" #include<cstring> using std::cin; using std::cout; MyString::MyString(const char * s) { len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); } MyString::MyString() { len = 4; str = new char[1]; str[0] = '\0'; } MyString::MyString(const MyString & st) { len = st.len; str = new char[len + 1]; std::strcpy(str, st.str); } MyString::~MyString() { delete[]str; } MyString & MyString::operator=(const MyString st) { if (this == &st) return *this; delete[]str; len = st.len; str = new char[len + 1]; std::strcpy(str, st.str); return *this; } MyString & MyString::operator=(const char *s) { delete[]str; len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); return *this; } char & MyString::operator[](int i) { return str[i]; } const char & MyString::operator[](int i) const { return str[i]; } bool operator<(const MyString & st1, const MyString & st2) { return (std::strcmp(st1.str, st2.str) < 0); } bool operator>(const MyString & st1, const MyString & st2) { return st1 < st2; } bool operator==(const MyString & st1, const MyString & st2) { return (std::strcmp(st1.str, st2.str) == 0);; } ostream & operator<<(ostream & os, const MyString & st) { os << st.str; return os; } istream & operator >> (istream & is, MyString & st) { char temp[MyString::CINLIM]; is.get(temp, MyString::CINLIM); if (is) st = temp; while (is && is.get() != '\n') continue; return is; }
下面的是笔者的微信公众号,欢迎关注,会持续更新c++、python、tensorflow、机器学习、深度学习等系列文章