C++学习——操作符重载

二十、操作符重载

1.基本概念

操作符重载就是一些具有特殊名字的函数,使用“operator#”表示,通过重载可以定义“#”符号的功能。

例如:复数“x+yi”

(1+2i)+(3+4i)=(4+6i)

2.双目操作符,+,-,*,.......

①表示的结果是右值,不能对表达式结果再赋值

②左右操作数既可以是左值,也可以是右值

③两种实现方式:
1)成员函数形式(左调右参)

形如L#R的表达式可以被编译器处理成L.operator#(R) 成员函数调用形式,该函数的返回结果就是表达式的结果

2)全局函数形式

形如L#R的表达式也可以被编译器处理成operator#(L,R)全局函数调用形式,该函数的返回结果就是表达式的结果

注:使用friend关键字将一个全局函数声明为某个类的友元,友元函数可以访问类中的任何成员

参考代码:

#include <iostream>
using namespace std;
class Complex{
public:
    Complex(int r,int i):m_r(r),m_i(i){}
    void print(void)const{
        cout << m_r << '+' << m_i << 'i'
            << endl;
    }
    //c1+c2 ==> c1.operator+(c2)
    /*三个const的作用:
      1.修饰返回值禁止对表达式赋值(返回右值)
      2.常引用,支持常量型的右操作数
      3.常函数,支持常量型的左操作数
    */
    const Complex operator+(
            const Complex& c)const{
        Complex res(m_r+c.m_r,m_i+c.m_i);
        return res;
    }
private:
    int m_r;//实部
    int m_i;//虚部
    friend const Complex operator-(
         const Complex& l,const Complex& r);
};
const Complex operator-(
    const Complex& l,const Complex& r){
    Complex res(l.m_r-r.m_r,l.m_i-r.m_i);
    return res;
}
int main(void)
{
    Complex c1(1,2);
    Complex c2(3,4);
    c1.print();
    c2.print();

    //Complex c3 = c1.operator+(c2)
    Complex c3 = c1 + c2;
    c3.print();//4+6i

    return 0;
}

3.赋值类双目操作符,+=,-=,......

①表达式结果是左值

②左操作数一定是左值,右操作数可以是左值也可以是右值

③两种实现方式

1)成员函数形式

L#R ==> L.operator#(R);

2)全局函数形式

L#R ==>operator#(L,R);

参考代码:
 

#include <iostream>
using namespace std;
class Complex{
public:
    Complex(int r,int i):m_r(r),m_i(i){}
    void print(void) const {
        cout << m_r << '+' << m_i << 'i'
            << endl;
    }
    //+=:成员函数形式
    //c1+=c2 ==> c1.operator+=(c2)
    Complex& operator+=(const Complex& c){
        m_r += c.m_r;
        m_i += c.m_i;
        return *this;
    }
    //-=:全局函数形式
    //c1-=c2 ==> operator-=(c1,c2)
    //友元函数可以直接定义在类的内部,但是本
    //质还是全局函数
    friend Complex& operator-=(
            Complex& l,const Complex& r){
        l.m_r -= r.m_r;
        l.m_i -= r.m_i;
        return l;
    }
private:
    int m_r;
    int m_i;
};
int main(void)
{
    Complex c1(1,2);
    Complex c2(3,4);
    c1 += c2;//c1.operator+=(c2)
    c1.print();//4+6i
    
    Complex c3(5,6);
    (c1+=c2) = c3;
    c1.print();//5+6i
    
    c1 -= c2;
    c1.print();//2+2i
}

4.单目操作符

1)计算类单目操作符

①表达式的结果是右值,不能对表达式结果进行赋值

②操作数既可以是左值也可以是右值

③两种实现形式

成员函数形式:#O ==> O.operator#()

全局函数形式:#O ==>operator#(O)

参考代码:
 

#include <iostream>
using namespace std;

class Integer{
public:
    Integer(int i):m_i(i){}
    void print(void)const{
        cout << m_i << endl;
    }
    //-(取负):成员函数形式
    const Integer operator-(void)const{
        Integer res(-m_i);
        return res;
    }
    //~:全局函数形式(自定义表示平方)
    friend const Integer operator~(
            const Integer& i){
        Integer res(i.m_i * i.m_i);
        return res;
    }
private:
    int m_i;
};
int main(void)
{
    Integer i(10);
    Integer j = -i;//i.operator-()
    j.print();//-10
    j = ~i;//operator~(i);
    j.print();//100
    return 0;
}

2)自增减单目操作符

前缀:

①表达式结果是左值,就是操作数的自身

②操作数必须是左值

③两种实现形式:

成员函数形式:#O ==> O.operator#();

全局函数形式:#O ==> operator#(O);

后缀:
①表达式结果是右值,是操作数自增减前的副本

②操作数必须是左值

③三种实现形式:
成员函数形式:#O ==> O.operator#(int /*哑元*/)

全局函数形式:O# ==> operator#(O,int/*哑元*/)

参考代码:
 

#include <iostream>
using namespace std;
class Integer{
public:
    Integer(int i):m_i(i){}
    void print(void)const{
        cout << m_i << endl;
    }
    //前++:成员函数形式
    Integer& operator++(void){
        ++m_i;
        return *this;
    }
    //前--:全局函数形式
    friend Integer& operator--(Integer& i){
        --i.m_i;
        return i;
    }
    //后++:成员函数形式
    const Integer operator++(int/*哑元*/){
        Integer old = *this;
        ++*this;//++m_i;
        return old;
    }
    //后--:全局函数形式
    friend const Integer operator--(
            Integer& i,int/*哑元*/){
        Integer old = i;
        --i;//--i.m_i;
        return old;
    }
private:
    int m_i;
};
int main(void)
{
    Integer i(10);
    Integer j = ++i;
    i.print();//11
    j.print();
    j = ++++i;
    i.print();//13
    j.print();
    
    j = --i;
    i.print();//12
    j.print();
    j = ----i;
    i.print();//10
    j.print();

    j = i++;
    i.print();//11
    j.print();//10
    //j = i++++;//error
    
    j = i--;
    i.print();//10
    j.print();//11
    //j = i----;//error

    return 0;
}

5.输入(输出)和输入(提取)操作符:<<,>>

1)功能:实现自定义类型对象的输入和输出

注:实现自定义类型对象的输入和输出

注:只能用全局函数形式

	#include <iostream>
	ostream//标准输出类
	istream//标准输入类
	friend ostream& operator<<(
			ostream& os,const Right& r){...}	
	friend istream& operator>>(
			istream& is,Right& r){...}

参考代码:
 

#include <iostream>
using namespace std;
class Complex{
public:
    Complex(int r,int i):m_r(r),m_i(i){}
    friend ostream& operator<<(
            ostream& os,const Complex& c){
        os << c.m_r << '+' << c.m_i << 'i';
        return os;
    }
    friend istream& operator>>(
            istream& is,Complex& c){
        is >> c.m_r >> c.m_i;
        return is;
    }
private:
    int m_r;
    int m_i;
};
int main(void)
{
    Complex c1(1,2);
    Complex c2(3,4);
    //operator<<(cout,c1)
    cout << c1 << endl;
    cout << c1 << ',' << c2 << endl;
    Complex c3(0,0);
    cin >> c3;
    cout << c3 << endl;
    return 0;
}

6.下标操作符:[ ]

1)功能:可以让一个对象像数组一样去使用

注:非常对象返回左值,常对象返回右值

	string s = "abc";
	//s.operator[](0) = 'A'
	s[0] = 'A';//ok,返回左值,
	--------------------
	const string s = "abc";
	//s.operator[](0) = 'A'
	s[0] = 'A';//error,返回右值

参考代码:

#include <iostream>
using namespace std;

//实现一个容器类,里面可以存放若干个int
class Array{
public:
    Array(size_t size){
        m_arr = new int[size];
    }
    ~Array(void){
        delete[] m_arr;
    }
    //适用非const对象,返回左值
    int& operator[](size_t i){
        return m_arr[i];
    }
    //适用常对象,返回右值
    const int& operator[](size_t i)const{
        return m_arr[i];
    }
private:
    int* m_arr;
};
int main(void)
{
    Array arr(5);
    //arr.operator[](0) = 123;
    arr[0] = 123;
    const Array& rarr = arr;
    cout << rarr[0] << endl;//123
    //rarr[0] = 321;//应该error
    return 0;
}


7.函数调用操作符:()

1)功能:让对象可以像函数一样去调用

注:对参数的个数、类型和返回类型都没有限制

A a;
a(10,1.23); //a.operator()(10,1.23)

参考代码:

#include <iostream>
using namespace std;
class Func{
public:
    int operator()(int a,int b){
        return a+b;
    }
    int operator()(int a){
        return a*a;
    }
};
int main(void)
{
    Func func;
    //func.operator()(10,20)
    cout << func(10,20) << endl;//30
    //func.operator()(10)
    cout << func(10) << endl;//100
    return 0;
}

8.new/delete操作符

static void* operator new(size_t size){}
static void* operator delete(void* p){}

参考代码:

#include <iostream>
#include <cstdlib>
using namespace std;
class A{
public:
    A(void){
        cout << "A的构造函数" << endl;
    }
    ~A(void){
        cout << "A的析构函数" << endl;
    }
    static void* operator new(size_t size){
        cout << "A的new" << endl;
        void* pv = malloc(size);
        return pv;
    }
    static void operator delete(void* pv){
        cout << "A的delete" << endl;
        free(pv);
    }
};
int main(void)
{
    //1)A* pa=(A*)A::operator new(sizeof(A))
    //2)pa->构造函数
    A* pa = new A;

    //1)pa->析构函数
    //2)A::operator delete(pa);
    delete pa;
}

9.操作符重载限制

1)不是所有操作符都能重载,下面操作符不能重载

①作用域限制操作符“::”

②直接成员访问操作符“.”

③直接成员指针解引用操作符“.*”

④条件操作符“?:”

⑤字节长度操作符“sizeof()”

⑥类型信息操作符“typeid()”

2)如果一个操作符所有操作数都是基本类型,则无法重载

3)操作符重载不会改变编译器预定义的优先级

4)操作符重载不能改变操作数的个数

5)无法通过操作符重载发明新的符号

6)只能用成员函数形式的操作符

猜你喜欢

转载自blog.csdn.net/isco22/article/details/88284285