C++运算符重载
什么是运算符重载
- 运算符重载赋予运算能够操作自定义类型。
- 运算符重载前提条件: 必定存在一个自定义类型
- 运算符重载实质: 就是函数调用
- 友元重载
- 类重载
- 在同一自定义类型中,一个运算符只能被重载一次
- C++重载只能重载已有的运算符,不能重载没有
- C++重载一般情况不能违背运算符原来的含义(就算语法正确)
- 注意点:
- . ,.* ,?:,:: 不能被重载
#include <iostream> #include <string> using namespace std; class MM { public: MM() {} MM(string name, int score) :name(name), score(score) {} protected: string name; int score; }; int main() { int a = 1; int b = 2; int sum = a + b; MM mm("小芳", 6); MM girl("小芳", 2); //error: 没有与这些操作数匹配 "xxx" 运算符 //MM result = mm + girl; //错误 return 0; }
重载写法
重载函数的写法
//函数定义方式 函数返回值类型 函数名(参数) { //函数体; } //运算符重载也是函数,只是函数名写法不同 //函数名: operator加上运算符组成函数名 //参数: // 友元重载: 参数个数等于操作数 // 类成员函数: 参数个数等于操作-1 // 函数返回值类型:运算符组成表达式 最终结果是什么类型就返回类型 // int a; int b; a+b 返回int // 函数体:写你真正要实现的效果
友元重载
#include <iostream> #include <string> using namespace std; class MM { public: MM() {} MM(string name, int score) :name(name), score(score) {} void print() { cout << name << "\t" << score << endl; } //友元重载 friend MM operator+(MM a, MM b); //加法重载函数的声明 protected: string name; int score; }; MM operator+(MM a, MM b) { return MM(a.name, a.score+b.score); //返回一个匿名对象 } int main() { int a = 1; int b = 2; int sum = a + b; MM mm("小芳", 6); MM girl("小芳", 2); //error: 没有与这些操作数匹配 "xxx" 运算符 //重载函数的隐式调用 -->mm + girl 解析为:operator+(mm, girl) MM result = mm + girl; //显示绿色就是运算符重载 result.print(); //重载函数显示调用:按照函数的调用方式 MM res = operator+(mm, girl); //operator+:函数名 参数 //string aa("12"); //string bb("2323"); //cout << (aa > bb) << endl; return 0; }
类重载
#include <iostream> #include <string> using namespace std; class MM { public: MM() {} MM(string name, int score) :name(name), score(score) {} void print() { cout << name << "\t" << score << endl; } //友元重载 friend MM operator+(MM a, MM b); //加法重载函数的声明 protected: string name; int score; }; //类成员函数少一个参数: 对象本身可以表示参数 MM MM::operator-(MM object) { return MM(this->name, this->score - object.score); } int main() { MM mul = mm.operator-(girl); //类重载显示调用,跟调用普通成员函数一样的 mul.print(); MM girlFriend = mm - girl; //编译器mm - girl翻译为: mm.operator-(girl) girlFriend.print(); return 0; }
特殊运算符重载
- 通常情况:单目运算符用类成员函数重载,双目用友元重载
- = ,(),->,[] 只能采用成员函数重载
- ++ --运算符重载
- 增加一个无用参数,标识是后置++或者--
- 流运算符重载(>> <<)
- 输入流对象(cin): istream类
- 输出流对象(cout): ostream类
- 流重载必须用引用
- 流重载一定要用友元重载
- 后缀重载
#include <iostream> #include <string> #include <thread> using namespace std; class MM { public: MM() {} MM(string name, int age) :name(name), age(age) {} void print() { cout << name << "\t" << age << endl; } //MM operator=(MM) = delete; //删掉默认的 //函数重载 void operator=(int data) { this->age += data; } //++ 为例 MM operator++() //前置 { this->age++; return *this; //返回对象本身 } MM operator++(int) //后置的 { return MM(this->name, this->age++); } //流运算符的重载 friend ostream& operator<<(ostream& out, MM& object); friend istream& operator>>(istream& in, MM& object); private: string name; int age; }; ostream& operator<<(ostream& out, MM& object) { //out当做cout用 out << object.name << "\t" << object.age << endl; return out; } istream& operator>>(istream& in, MM& object) { cout << "输入对象属性:"; //in当做cin用即可 in >> object.name >> object.age; return in; } //文本重载, 一般写成下划线系列 //后缀的重载 unsigned long long operator""_h(unsigned long long data) { return data * 60 * 60; } unsigned long long operator""_m(unsigned long long data) { return data * 60; } unsigned long long operator""_s(unsigned long long data) { return data; } int main() { MM mm("小芳", 18); MM girl; girl = mm; //每一个类中都存在默认的赋值重载 girl = 8; girl.print(); MM result = ++girl; result.print(); girl.print(); result = girl++; result.print(); girl.print(); cin >> girl; cout << girl << endl; //this_thread::sleep_for(10s); cout << 1_h << endl; cout << (1_h + 30_m + 49_s) << endl; return 0; }
对象的隐式转换
对象隐式转换: 就是让对象能够赋值给普通数据
//operator 转换的类型() //{ // return 要转换类型的数据; //} #include <string> #include <iostream> using namespace std; class MM { public: MM() {} MM(string name, int age) :name(name), age(age) {} operator int() { return this->age; } protected: string name; int age; }; int main() { MM mm("mm", 39); int age = mm; cout << age << endl; return 0; }
()运算符的重载
仿函数
让类型可以模仿函数调用的行为: 函数名(参数); 类名() 调用的函数行为
#include <iostream> #include <algorithm> #include <functional> using namespace std; class Data { public: //operator()组成函数名 void operator()() { cout << "无参重载()" << endl; } void operator()(int a, int b) { cout << "有参重载(a,b)" << endl; } protected: }; int main() { //greater<int>(); //比较准则 //int array[5] = { 3,4,1,2,32 }; //sort(array, array + 5, greater<int>()); //for (auto& v : array) //{ // cout << v << "\t"; //} //cout << endl; Data data; data.operator()(); //显式调用 data.operator()(1, 2); //显式调用 data(); //隐式调用 data(1, 2); //隐式调用 Data{}(); //{}帮助识别 Data() Data{}(2, 3); return 0; }
运算符重载案例分析
智能指针
智能指针是用对象方式管理new的内存,可以做到自动释放(本质是析构函数自动调用)内存的功能
#include <iostream> #include <memory> using namespace std; class Auto_Ptr { public: Auto_Ptr(int* ptr) :ptr(ptr) {} ~Auto_Ptr() { if (ptr) { delete ptr; ptr = nullptr; } } //访问指针 int* operator->() { return this->ptr; } //访问数据 int& operator*() { return *ptr; } //禁止拷贝,禁止赋值 Auto_Ptr(Auto_Ptr&) = delete; Auto_Ptr& operator=(Auto_Ptr&) = delete; protected: int* ptr; }; int main() { Auto_Ptr object(new int(1999)); cout << *object << endl; //shared_ptr<int> p(new int(19999)); //cout << *p << endl; //shared_ptr<double> p2(new double(19.99)); //cout << *p2 << endl; return 0; }
封装数组
#include <iostream> #include <vector> //动态数组 using namespace std; class my_vector { public: my_vector(int capacity = 10) :capacity(capacity) { mem = new int[capacity] {0}; curSize = 0; } void push_back(int data) { mem[curSize++] = data; } int* begin() { return mem + 0; } int* end() { return mem + capacity; } int& operator[](int index) { if (curSize < index) curSize = index; return mem[index]; } //万金油函数 int size() { return curSize; } int empty() { return curSize == 0; } ~my_vector() { if (mem) { delete[] mem; mem = nullptr; } } protected: int* mem; int capacity; int curSize; }; int main() { my_vector vec; for (int i = 0; i < 3; i++) { vec[i] = i; } for (auto v : vec) { cout << v << "\t"; } cout << endl; cout << vec.size() << endl; for (int i = 0; i < vec.size(); i++) { cout << vec[i] << "\t"; } cout << endl; return 0; }
迭代器实现
//迭代器就是让一个类中类去遍历数据
#include <iostream> #include <string> using namespace std; struct Node { int data; Node* next; Node() :next(nullptr){} Node(int data) :data(data), next(nullptr) {} Node(int data, Node* next) :data(data), next(next) {} }; class List { public: List() :headNode(new Node),curSize(0){} void push_front(int data) { headNode->next = new Node(data, headNode->next); curSize++; } Node* begin() { return headNode->next; } Node* end() { return nullptr; } class iterator { public: iterator() :pmove(nullptr) {} void operator=(Node* pmove) { this->pmove = pmove; } bool operator!=(Node* pmove) { return this->pmove != pmove; } iterator operator++() { this->pmove = this->pmove->next; //链表++不了 return *this; } int operator*() { return this->pmove->data; //*运算访问数据 } private: Node* pmove; //需要指针访问数据 }; protected: Node* headNode; int curSize; }; void my_list() { List list; for (int i = 0; i < 3; i++) { list.push_front(i); } List::iterator it; for (it = list.begin(); it != list.end(); ++it) { cout << *it << " "; } cout << endl; } int main() { string str = "ILoveyou"; for (int i = 0; i < str.size(); i++) { cout << str[i]; } cout << endl; //类中类访问一个容器数据 string::iterator it; for (it = str.begin(); it != str.end(); it++) { cout << *it; //*指针取值运算 } cout << endl; //cout << *str.end() << endl; my_list(); return 0; }
重载的特殊问题
//对象与常量运算 #include <iostream> #include <string> using namespace std; class Data { public: Data() {} Data(int num) :num(num) {} //friend Data operator+(Data data, int num); //friend Data operator+( int num, Data data); //Data operator+(Data data) //{ // return Data(this->num + data.num); //} void print() { cout << num << endl; } friend Data operator+(Data data1, Data data2); protected: int num; }; //Data operator+(Data data, int num) //{ // return Data(data.num + num); //} //Data operator+(int num, Data data) //{ // return Data(num + data.num); //} Data operator+(Data data1, Data data2) { return Data(data1.num + data2.num); } int main() { Data data(1); Data temp; //data.成员函数(1); temp = data + 1; //1+data : 1.成员函数() temp = 1 + data; //类成员函数没办法完成 temp.print(); return 0; }