码迷,mamicode.com
首页 > 编程语言 > 详细

C++ 运算符重载的注意点

时间:2015-06-26 09:28:29      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:c++

运算符重载包括:双目运算符重载、单目运算符重载、流运算符重载、转换构造函数、类型转换函数

重载运算符的函数一般格式如下:
函数类型 operator 运算符名称 (形参表列)
{
// 对运算符的重载处理
}

1. 双目运算符重载

双目:有2个操作数的运算符
重载函数可以为类成员函数或者是类的友元函数:
- 当是成员函数时,有一个隐藏参数(当前类),因此只有一个显示参数:如
Complex operator+(const Complex &b);
Complex operator+(const double &d);
- 当是友元函数时,必须显式给出两个参数,之所以使用友元函数,是为了将操作符重载为全局的:
因为

Complex c(1,1);
Complex d = c + 10.0; // 正确
Complex e = 10.0 + c; // 错误

对于第3行,无法从浮点数“10.0”获得如何操作。
因此将重载函数声明为友元函数,则可以全局的对 10.0 和 c 进行参数匹配.

#include <iostream>
using namespace std;
class Complex {
private:
    double real;
    double imag;
public:
    Complex(double real, double imag) {this->real = real;this->imag = imag;}
    Complex() {real = 0.0;imag = 0.0;}
    // 转换构造函数:只能有一个参数
public:
    Complex operator+(const Complex &b);
    friend Complex operator+(const Complex &c, const double & d);
    friend Complex operator+(const double & d, const Complex &c); // 友元函数可以

    void Print() {
        if (imag < 0)
            cout << real << imag << "i" << endl;
        else 
            cout << real << "+" << imag <<"i" << endl;
    }
};
// 成员函数重载
Complex Complex::operator+(const Complex &b) {
        return Complex(this->real+b.real, this->imag+b.imag);
}
// 友元函数不能省略参数,重载成一个全局操作符
// 友元函数可以访问友元类的私有成员
Complex operator+(const double &d, const Complex &c) {
    return Complex(c.real+d, c.imag);
}
Complex operator+(const Complex &c, const double &d) {
    return Complex(c.real+d, c.imag);
}

int main() {
    Complex a(1,-2);
    Complex b(3,-1);
    Complex c = a+b;
    Complex f = 10+a;
    Complex g = b + 10;
    c.Print();
    f.Print();
    g.Print();
}

2. 单目运算符重载

重点的讨论自增自减的运算符重载。参考以下程序可以观察到:
前缀式操作符和后缀式操作符重载的区别在于,带有参数 int,以及返回值是不同的:
C++规定:前缀式操作符,返回被增量或被减量对象的引用;后缀式操作符,返回被增量或被减量对象做增或减操作之前的副本

MyClass operator++(); // 前缀式,++i;
MyClass operator++(int); // 后缀式,i++

一个基于Time的类例程如下:

#include <iostream>
using namespace std;
class Time {
private:
    int minute;
    int sec;
public:
    Time():minute(0), sec(0) {};
    Time(int m, int s):minute(m), sec(s) {};
    // 前缀式操作符,返回被增量或被减量对象的引用;
    Time operator++() {
        if (++sec >= 60) {
            minute++;
            sec -= 60;
        }
        return *this;
    }
    //后缀式操作符,返回被增量或被减量对象做增或减操作之前的副本
    Time operator++(int) {
        Time temp(*this);
        ++(*this); 
        return temp; // 对象本身已经实现了自增操作,但返回的是未自增之前的副本
    }
    void print() {
        cout << minute << ":" << sec << endl;
    }
};

int main() {
    cout << "开始时间 12:58" << endl;
    Time time1(12, 58);
    for (int i = 0; i < 5; i++) {
        (++time1).print();
    }
    cout << "开始时间 22:58" << endl;
    Time time2(22,58);
    for (int i = 0; i < 5; i++) {
        (time2++).print();
    }

}

3. 流运算符重载

对“<<”和“>>”重载的函数形式如下:
istream & operator >> (istream &, 自定义类 &);
ostream & operator << (ostream &, 自定义类 &);
即重载运算符“>>”的函数的第一个参数和函数的类型都必须是istream&类型,第二个参数是要进行输入操作的类。重载“<<”的函数的第一个参数和函数的类型都必须是ostream&类型,第二个参数是要进行输出操作的类。因此,只能将重载“>>”和“<<”的函数作为友元函数或普通的函数,而不能将它们定义为成员函数。
操作符重载之所以有返回值是为了返回输入/输出的状态,以便连续的输入输出。
详细参见:http://c.biancheng.net/cpp/biancheng/view/220.html
代码案例参考双目运算符中的代码块。

#include <iostream>
using namespace std;
class Complex {
private:
    double real;
    double imag;
public:
    Complex(double real, double imag) {this->real = real;this->imag = imag;}
    Complex() {real = 0.0;imag = 0.0;}
public:
    friend istream& operator>>(istream &, Complex &);
    friend ostream& operator<<(ostream &, Complex &);
};

// 流操作符重载
istream& operator>>(istream &input, Complex &c) {
    input >> c.real >> c.imag;
    return input; // 返回流输入对象,以便连续输入
}
ostream& operator<<(ostream &output, Complex &c) {
    output << c.real;
    if (c.imag >= 0)
        output << "+";
    output << c.imag << "i" << endl;
    return output;
}

int main() {
    Complex x, y;
    cin >> x >> y;
    cout << x << y;
}

4. 转换构造函数

转换构造函数只有一个形参,如
Complex(double r) {real=r;imag=0;}
其作用是将double型的参数r转换成Complex类的对象,将r作为复数的实部,虚部为0。
和操作符重载配合,简化操作符重载的实现.
如下所示,只需要一个操作符 + 的重载和转换构造函数,即可满足所有 + 操作的情况,并满足了交换律。注意上述操作符重载必须为友元函数或者普通函数的形式(非成员函数)。

#include <iostream>
using namespace std;
class Complex {
private:
    double real;
    double imag;
public:
    Complex(double real, double imag) {this->real = real;this->imag = imag;}
    Complex() {real = 0.0;imag = 0.0;}
    // 转换构造函数:只能有一个参数
    Complex(double real) {
        this->real = real;
        this->imag = 0;
    }
public:
    friend Complex operator+(const Complex &a, const Complex &b);
    void Print() {
        if (imag < 0)
            cout << real << imag << "i" << endl;
        else 
            cout << real << "+" << imag <<"i" << endl;
    }
};
Complex operator+(const Complex &a, const Complex &b) {
    return Complex(a.real+b.real, a.imag+b.imag);
}

int main() {
    Complex a(1,-2);
    Complex b(3,-1);
    Complex e = a + b;
    e.Print();
    Complex f = 10 + a; // 自动将 10 ,转换成Complex的一个实例
    f.Print();
    Complex g = a + 10;
    g.Print();

}

5. 类型转换

用转换构造函数可以将一个指定类型的数据转换为类的对象。但是不能反过来将一个类的对象转换为一个其他类型的数据(例如将一个Complex类对象转换成double类型数据)。

C++提供类型转换函数(type conversion function)来解决这个问题。类型转换函数的作用是将一个类的对象转换成另一类型的数据。如果已声明了一个Complex类,可以在Complex类中这样定义类型转换函数:
operator double( )
{
return real;
}
注意:没有函数返回类型,没有参数。返回类型自动根据重载的类型名一致。类型转换函数只能作为成员函数(转换的是本类的对象)。

#include <iostream>
using namespace std;
class Complex {
private:
    double real;
    double imag;
public:
    Complex(double real, double imag) {this->real = real;this->imag = imag;}
    Complex() {real = 0.0;imag = 0.0;}
    operator double() {
        return real;
    }
public:
    void Print() {
        if (imag < 0)
            cout << real << imag << "i" << endl;
        else 
            cout << real << "+" << imag <<"i" << endl;
    }
};
int main() {
    Complex a(1,-2);
    Complex b(3,-1);
    double d = a + 10;
    cout << d << endl;
    cout << a + 10 << endl;
    cout << 10 + b << endl;
}

参考资料:C++运算符重载详解—什么是运算符重载、运算符重载的方法和规则

C++ 运算符重载的注意点

标签:c++

原文地址:http://blog.csdn.net/quzhongxin/article/details/46640135

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!