C++类与对象--5 运算符重载
对已有的运算符进行重新定义,赋予不同的功能,以适应不同的数据类型
5.1 加号运算符
-
实现两个自定义数据类型的加运算
(1)通过成员函数实现“+”重载
class Number
{
public:Number(int a, int b):m_A(a),m_B(b){}Number(){}Number operator+(Number & num) // 成员函数重载+运算符{Number newNum;newNum.m_A = this->m_A + num.m_A;newNum.m_B = this->m_B + num.m_B;return newNum;}int m_A;int m_B;
};
Number num1(10, 15);
Number num2(15, 20);
Number num3 = num1 + num2; // 本质-->Number num3 = num1.operator+(num2);
(2)通过全局函数实现“+”重载
class Number
{
public:Number(int a, int b):m_A(a),m_B(b){}Number(){}
int m_A;int m_B;
};
Number operator+(const Number & num1, const Number & num2) // 全局函数重载+运算符
{Number newNum;newNum.m_A = num1.m_A + num2.m_A;newNum.m_B = num1.m_B + num2.m_B;return newNum;
}
Number num1(10, 15);
Number num2(15, 20);
Number num3 = num1 + num2; // 本质-->Number num3 = operator+(num1, num2);
(3)重载的运算符也可以发生函数重载-->实现不同功能的加法
class Number
{
public:Number(int a, int b):m_A(a),m_B(b){}Number(){}
int m_A;int m_B;
};
Number operator+(const Number & num1, const Number & num2) // 全局函数重载+运算符
{Number newNum;newNum.m_A = num1.m_A + num2.m_A;newNum.m_B = num1.m_B + num2.m_B;return newNum;
}
Number operator+(const Number & num1, int & a) // +运算符函数重载(形参类型不同)
{Number newNum;newNum.m_A = num1.m_A + a;newNum.m_B = num1.m_B + a;return newNum;
}
Number num1(10, 15);
Number num2(15, 20);
Number num3 = num1 + num2; // 本质-->Number num3 = operator+(num1, num2);
int a = 10;
Number num4 = num1 + a; // 本质-->Number num4 = operator+(num1, a);
5.2 左移运算符重载
-
实现自定义数据类型输出
(1)只能使用全局函数实现“<<”重载
class Number
{
public:int m_A = 10;int m_B = 20;
};
std::ostream & operator<<(std::ostream & cout, Number & num)
{cout << num.m_A << num.m_B;return cout; // 用于链式编程 cout << endl;
}
int main()
{Number num;std::cout << num << std::endl; // 本质operator<<(cout, num)// 重载的<<函数返回了ostream对象,可以链式编程
}
(2)“<<”重载函数访问私有成员-->友元
class Number
{friend std::ostream & operator<<(std::ostream & cout, Number & num); // 重载函数友元
private:int m_A = 10;int m_B = 20;
};
std::ostream & operator<<(std::ostream & cout, Number & num)
{cout << num.m_A << num.m_B;return cout; // 用于链式编程 cout << endl;
}
int main()
{Number num;std::cout << num << std::endl;
}
5.3 递增运算符重载
-
实现自定义数据类型自加
(1)前置++重载
class MyInt
{
public:MyInt(int a):m_a(a){}MyInt & operator++() // 重载前置++,用于对象成员自加{this->m_a = this->m_a + 1;retun *this;}int m_a;
};
std::ostream & operator<<(std::ostream & cout, MyInt a) // 重载左移运算符,用于对象输出
{cout << a.m_a;return cout;
}
int main()
{MyInt myint(10);std::cout << ++myint << std::endl;
}
(2)后置++重载
class MyInt
{
public:MyInt(int a):m_a(a){}MyInt operator++(int) // 重载后置++,使用int占位参数区分前置++和后置++重载{Myint tempint = *this; // 默认拷贝构造this->m_a = this->m_a + 1;return tempint;}
int m_a;
};
5.4 赋值运算符重载
- C++编译器为类提供默认赋值运算符重载函数operator=,对属性进行赋值
- 自定义赋值运算符重载,实现对自定义类型数据进行赋值
- 存在堆区成员属性:先清空自身堆区成员,再进行深拷贝
- 两个已经创建好的对象,使用=,则使用的是重载赋值运算符(与默认拷贝函数的区别)
class Person
{
public:std::string m_name;int * m_age;
Person(int age, std::string name){m_name = name;m_age = new int(age);}Person & operator=(const Person & p) // 重载赋值运算符{m_name = p.m_name;if(m_age != NULL) // 先删除自身从堆申请的内存{delete m_age;m_age = NULL;}m_age = new int(*p.m_age); // 使用传入的数据重新从堆区申请内存return *this; // 返回当前对象,用于链式编程:a=b=c}~Person(){if(m_age != NULL){delete m_age;m_age = NULL;}}
};
void test01()
{Person p1(10, "zhangsan");Person p2(30, "lisi");Person p3(20, "wangwu");p3 = p1 = p2;
}
5.5 关系运算符重载
-
重载关系运算符,实现自定义数据类型之间的比较
class Person
{
public:int m_age;std::string m_name;Person(int age, std::string name):m_age(age),m_name(name){}bool operator==(const Person & p) // 重载==运算符,判断两个对象是否相等{if((m_age == p.m_age) && (m_name == p.m_name)){return true;}return false;}bool operator!=(const Person & p) // 重载!=运算符,判断两个对象是否不相等{if((m_age == p.m_age) && (m_name == p.m_name)){return false;}return true;}
};
5.6 函数调用运算符重载
-
重载括号运算符,实现仿函数调用
class MyPrint
{
public:void operator()(int val) // 重载(),实现仿函数{std::cout << val << std::endl;}
};
int main()
{MyPrint printFunc;printFunc(10); // 类似函数的调用
}