7. C++运算符重载
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;
}