前言
参考资料:http://c.biancheng.net/cplus/
一.运算符重载
运算符重载:定义一个函数,重载某个运算符。
运算符重载的格式:
返回值类型 operator 运算符名称(参数列表){};
能够重载的运算符如下:
可重载的运算符列表1 | 可重载的运算符列表2 |
---|---|
+, -, *, /, %, ^, ++, – | |, &, ||, && |
!=, ==, <=, >= | ~, !, <<, >>, -> |
=, +=, -=, *=, /=, %=, ^= | (), [] |
注意,有四个运算符不能被重载。
不能重载的运算符 |
---|
长度运算符sizeof |
条件运算符:? |
成员选择符. |
域解析运算符:: |
运算符重载不会改变运算符的优先级和用法,且重载函数中不能有默认的参数。
绝大部分运算符可以重载为成员函数、友元函数和全局函数
1)一元运算符由于只有一个形参作为运算符的右操作数,一个this指针指向左操作数,因此一般重载为成员函数。
2)二元运算符需要定义两个形参,为了满足交换律、结合律等运算规则,通常重载为友元函数。
1.重载数学运算符
数学运算符分为四则运算符,关系运算符和自增自减运算符。
四则运算符有+,-,*,/,+=,-=,*=,/=其中+,-,*,/是二元运算符,以友元形式重载,+=,-=,*=,/=是一元运算符,使用成员函数重载。
关系运算符有>,<,>=,<=,==,!=。
自增自减运算符是++和–,是一元运算符,必须定义为成员函数重载。注意,需要区分前加和后加。
赋值运算符=只能重载为成员函数。
#include<iostream>
#include<string>
using namespace std;
class Real {
private:
double m_real;
public:
Real(double real = 0.0) :m_real(real) {};
//二元运算符,使用友元形式重载
friend Real operator+(const Real& r1, const Real& r2);
friend Real operator-(const Real& r1, const Real& r2);
friend Real operator*(const Real& r1, const Real& r2);
friend Real operator/(const Real& r1, const Real& r2);
friend bool operator==(const Real& r1, const Real& r2);
friend bool operator!=(const Real& r1, const Real& r2);
//一元运算符,使用成员函数形式重载
Real& operator+=(const Real& r);
Real& operator-=(const Real& r);
Real& operator*=(const Real& r);
Real& operator/=(const Real& r);
Real& operator=(const Real& r);
bool operator<(const Real& r);
bool operator>(const Real& r);
bool operator>=(const Real& r);
bool operator<=(const Real& r);
Real operator++(); //++i,前加
Real operator++(int); //i++,后加
//定义普通成员函数
double real() {
return m_real;
}
};
//定义重载函数
Real operator+(const Real& r1, const Real& r2) {
Real r;
r.m_real = r1.m_real + r2.m_real;
return r;
}
Real operator-(const Real& r1, const Real& r2) {
Real r;
r.m_real = r1.m_real - r2.m_real;
return r;
}
Real operator*(const Real& r1, const Real& r2) {
Real r;
r.m_real = r1.m_real * r2.m_real;
return r;
}
Real operator/(const Real& r1, const Real& r2) {
Real r;
r.m_real = r1.m_real / r2.m_real;
return r;
}
bool operator==(const Real& r1, const Real& r2) {
if (r1.m_real == r2.m_real) {
return true;
}
else {
return false;
}
}
bool operator!=(const Real& r1, const Real& r2) {
if (r1.m_real != r2.m_real) {
return true;
}
else {
return false;
}
}
Real& Real::operator+=(const Real& r) {
this->m_real += r.m_real;
return *this;
}
Real& Real::operator-=(const Real& r) {
this->m_real -= r.m_real;
return *this;
}
Real& Real::operator*=(const Real& r) {
this->m_real *= r.m_real;
return *this;
}
Real& Real::operator/=(const Real& r) {
this->m_real /= r.m_real;
return *this;
}
Real& Real::operator=(const Real& r) {
if (this != &r) {
//判断是否给自己赋值
this->m_real = r.m_real;
}
return *this;
}
bool Real::operator>(const Real& r) {
if (this->m_real > r.m_real) {
return true;
}
else {
return false;
}
}
bool Real::operator<(const Real& r) {
if (this->m_real < r.m_real) {
return true;
}
else {
return false;
}
}
bool Real::operator>=(const Real& r) {
if (this->m_real >= r.m_real) {
return true;
}
else {
return false;
}
}
bool Real::operator<=(const Real& r) {
if (this->m_real <= r.m_real) {
return true;
}
else {
return false;
}
}
Real Real::operator++() {
++m_real;
return *this;
}
Real Real::operator++(int) {
Real temp = *this;
m_real++;
return temp;
}
int main() {
Real r1(3);
Real r2(5);
Real r3 = r1 + r2;
Real r4 = r1 - r2;
Real r5 = r1 * r2;
Real r6 = r1 / r2;
cout << "r3=" << r3.real() << "\nr4=" << r4.real() << "\nr5=" << r5.real() << "\nr6=" << r6.real() << endl;
r3 += r1;
cout << "r3+r1=" << r3.real() << endl;
r4 -= r1;
cout << "r4-r1=" << r4.real() << endl;
r5 *= r2;
cout << "r5*r2=" << r5.real() << endl;
r6 /= r2;
cout << "r6/r2=" << r6.real() << endl;
Real r7;
r7 = r1;
cout << "r7=" << r7.real() << endl;
cout << "++r7=" << (++r7).real() << endl;
r7 = r1;
cout << "r7++=" << (r7++).real() << endl;
cout << (r1 == r2) << '\n' << (r1 != r2) << endl;
return 0;
}
2.重载输入输出运算符
输入输出运算符须重载为友元函数形式。
在相应的类中,对输入运算符>>的重载如下:
//在类中声明
friend istream& operator>>(istream& in, Real& r);
//在类外定义
istream& operator>>(istream& in, Real& r){
in >> r.m_real;
return in;
}
int main(){
Real r1;
cin >> r1;
}
同理,对输出运算符<<进行重载如下:
//类中声明
friend ostream& operator<<(ostream& out, Real& r);
//类外定义
ostream& operator<<(ostream& out, Real& r){
out << r.m_real << endl;
}
int main(){
Real r1;
cin >> r1;
cout << r1 << endl;
}
3.重载下标运算符[]
下标运算符必须以成员函数的形式进行重载。
开发时常用两种形式:
1)返回值类型 & operator[] (参数);
2)const 返回值类型 & operator[] (参数) const;
重载[]可对对象进行下标运算。
class Array {
public:
Array(int length = 0);
~Array();
int& operator[](int i);
const int& operator[](int i) const;
private:
int m_length; //表示数组长度
int* m_p; //数组指针
};
Array::Array(int length): m_length(length){
if(length == 0){
m_p = NULL;
}
else{
m_p = new int[length];
}
}
Array::~Array(){
delete[] m_p;
}
i
nt& Array::operator[](int i) {
return m_p[i];
}
const int& Array::operator[](int i) const {
return m_p[i];
}
4.重载类型强制转换运算符()
类型强制转换运算符()是一元运算符,只能重载为成员函数。
//在类内声明
operator int();
//在类外定义
Real::operator int() {
return (int)m_real;
}
int main(){
Real r8(2.554);
cout << "float(r8)=" << (float)r8 << endl;
}
二.拷贝
1.拷贝构造函数
以拷贝的形式初始化一个对象,调用拷贝构造函数。
如果不自己定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。
class Array {
public:
Array(int length = 0);
Array(const Array& arr); //声明拷贝构造函数
~Array();
int& operator[](int i);
const int& operator[](int i) const;
private:
int m_length; //表示数组长度
int* m_p; //数组指针
};
//定义拷贝构造函数,必须是const的引用
Array::Array(const Array& arr){
this->m_length = arr.m_length;
if(this->m_length == 0){
this->m_p = NULL;
}
else{
this->m_p = new int[length];
}
}
int main(){
Array arr1(10);
Array arr2(arr1); //调用拷贝构造函数
Array arr3 = arr1; //调用拷贝构造函数
return 0;
}
2.深拷贝与浅拷贝
浅拷贝:浅拷贝只对对象中的数据成员进行简单赋值给新创建的对象,而对指针成员,直接将新对象的指针成员指向被拷贝对象的真正成员。
深拷贝:对于对象中动态成员,不是简单赋值,而需要重新动态分配空间。因此必须显式定义深拷贝构造函数。