C++预定义中的运算符的操作对象只局限于基本的内置数据类型,但是对于我们自定义的类型(类)是没有办法操作的。但是大多时候我们需要对我们定义的类型进行类似的运算。
例如:
这个时候就需要我们对这么运算符进行重新定义,赋予其新的功能,以满足自身的需求。
加法运算符的重载
下面代码自定义了一个Person类,通过对+的重载实现,类中成员变量的加法。
#include <iostream>
using namespace std;
class Person {
friend void test01();
public:
Person(int a, int b);
//利用成员函数完成运算符重载
Person operator+(const Person& p) {
Person temp(0,0);
temp.m_a = this->m_a + p.m_a;
temp.m_b = this->m_b + p.m_b;
return temp; //调用了拷贝构造函数,创建了一个新的Person类返回
}
private:
int m_a;
int m_b;
};
Person::Person(int a, int b) :m_a(a), m_b(b) {}
void test01() {
Person p1(10, 10);
Person p2(10, 10);
Person p3 = p1 + p2;
cout << "p3.m_a=" << p3.m_a << endl;
cout << "p3.m_b=" << p3.m_b << endl;
}
int main() {
test01();
system("pause");
return 0;
}
从代码中可以看出重载运算符的模板。
<返回类型说明符> operator <运算符符号>(<参数表>)
{
<函数体>
}
operator是关键字,专门用于定义重载运算符的函数。我们可以将operator运算符名称
这一部分看做函数名,对于上面的代码,函数名就是operator+
。
在代码中,我们在类Person中重载了+运算符,因此重载只对Person类有效。当代码执行到Person p3 = p1 + p2的时候,会调用operation+(const Person &p)函数。因此代码转换为:
Person p3 = p1.operation+(p2);
因此实现了自定义类Person中成员变量的加法,完成了函数的重载。
实验结果:
运算符的重载函数不仅可以作为类的成员函数,也可以作为全局函数。更改代码如下:
#include <iostream>
using namespace std;
class Person {
friend void test01();
friend Person operator+ (const Person& p1, const Person& p2);
public:
Person(int a, int b);
利用成员函数完成运算符重载
//Person operator+(const Person& p) {
// Person temp(0,0);
// temp.m_a = this->m_a + p.m_a;
// temp.m_b = this->m_b + p.m_b;
// return temp; //调用了拷贝构造函数,创建了一个新的Person类返回
//}
private:
int m_a;
int m_b;
};
Person::Person(int a, int b) :m_a(a), m_b(b) {}
/*全局函数完成函数重载*/
Person operator+ (const Person & p1, const Person & p2) {
Person p3(0,0);
p3.m_a = p1.m_a + p2.m_a;
p3.m_b = p1.m_b + p2.m_b;
return p3;
}
void test01() {
Person p1(10, 10);
Person p2(10, 10);
Person p3 = p1 + p2;
cout << "p3.m_a=" << p3.m_a << endl;
cout << "p3.m_b=" << p3.m_b << endl;
}
int main() {
test01();
system("pause");
return 0;
}
实验结果:
输入输出运算符的重载:
#include <iostream>
using namespace std;
class Complex {
friend void test01();
friend istream& operator>>(istream& in, Complex& A);
friend ostream& operator<<(ostream& out, Complex& A);
friend Complex operator+(const Complex& A, const Complex& B);
public:
Complex();
Complex(double real, double imag);
private:
double m_imag;
double m_real;
};
Complex::Complex():m_real(0.0),m_imag(0.0){}
Complex::Complex(double real, double imag):m_real(real),m_imag(imag){}
//在全局范围内重载+
Complex operator+(const Complex& A, const Complex& B) {
Complex C;
C.m_real = A.m_real + B.m_real;
C.m_imag = A.m_imag + B.m_imag;
return C;
}
//输入运算符的重载 operator<<(cin , c);
istream& operator>>(istream& in, Complex& A){
in >> A.m_real >> A.m_imag;
return in;
}
//输出运算符的重载 operator>>(cout , c);
ostream& operator<<(ostream& out, Complex& A) {
out << A.m_imag << " " << A.m_imag;
return out;
}
void test01() {
Complex p3;
cin >> p3;
cout << p3;
}
int main()
{
test01();
system("pause");
return 0;
}
自增和自减运算符的重载:
#include <iostream>
using namespace std;
class Inter {
friend ostream& operator<<(ostream& out, Inter p);
public:
Inter() {
m_num = 0;
}
Inter& operator++() { //前置++的重载
this->m_num++;
return *this;
}
Inter& operator--() { //前置--的重载
this->m_num--;
return *this;
}
Inter operator++(int) { //后置++的重载
Inter temp = *this;
this->m_num++;
return temp;
}
Inter operator--(int) {
Inter temp = *this;
this->m_num--;
return temp;
}
private:
int m_num;
};
ostream& operator<<(ostream &out,Inter p) {
out << p.m_num;
return out;
}
void test01() {
Inter p;
cout << p++ << endl;
cout << p-- << endl;
cout << p << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
赋值运算符的重载:
#include <iostream>
using namespace std;
class Person {
public:
Person(int age) { /*构造函数*/
m_age = new int(age); //在堆区开辟内存
}
~Person() { /*析构函数*/
if (m_age != NULL) {
delete m_age;
m_age = NULL;
}
}
void operator=(Person &p) {
if (m_age != NULL) {
delete m_age;
m_age = NULL;
}
//编译器提供的代码是浅拷贝,在析构函数中存在内存多次删除
//m_age = p.m_age;
//提供深拷贝 解决浅拷贝的问题
m_age = new int(*p.m_age);
}
public:
int *m_age; //年龄的指针
};
void test01() {
Person p1(18);
Person p2(20);
p2 = p1;
cout << "P1年龄是:" << *p1.m_age << endl;
cout << "P2年龄是:" << *p2.m_age << endl;
}
int main() {
test01();
system("pause");
return 0;
}
关系运算符的重载:
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
Person(string name, int age):m_name(name), m_age(age) {} //构造函数
bool operator==(Person &p) {
if (this->m_name == p.m_name && this->m_age == p.m_age) {
return true;
}
else {
return false;
}
}
bool operator!=(Person& p) {
if (this->m_name == p.m_name && this->m_age == p.m_age) {
return false;
}
else {
return true;
}
}
public:
string m_name; //定义属性 名字/年龄
int m_age;
};
void test01() {
Person p1("张三", 18);
Person p2("张三", 18);
if (p1 == p2) {
cout << "一样" << endl;
}
else {
cout << "不一样" << endl;
}
}
void test02() {
Person p1("张三", 18);
Person p2("李四", 18);
if (p1 != p2) {
cout << "不一样" << endl;
}
else {
cout << "一样" << endl;
}
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
函数调用运算符的重载:
#include <iostream>
using namespace std;
//*函数调用运算符() 也可以重载
class MyPrint
{
public:
void operator()(string text)
{
cout << text << endl;
}
};
void test01()
{
//重载的()操作符 也称为仿函数
MyPrint myFunc;
myFunc("hello world");
}
class MyAdd
{
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
void test02()
{
MyAdd add;
int ret = add(10, 10);
cout << "ret = " << ret << endl;
//匿名对象调用
cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}
由于重载后使用的方式非常像函数的调用,因此称为仿函数。
仿函数没有固定写法,非常灵活。