跳转至

运算符重载

为了使用起来方便,增强功能。运算符重载就是一个函数,函数的名称要加上operator。

可重载运算符如下:

类型 运算符
算术 +、-、*、/、%
位运算 ^、&、|、~、<<、>>
逻辑 !、&&、||
比较 <、>、<=、>=、==、!=
赋值与复合赋值 =、+=、-=、*=、/=、%=、^=、&=、|=、<<=、>>=
自增与自减 ++、--
逗号 ,
下标与函数调用 []、()
成员访问 ->、->*
内存分配与释放 new、new[]、delete、delete[]

当前标准还支持 <=>(三路比较)和 co_await(协程等待)的重载。+、-、*、& 的一元和二元形式均可重载。

以下运算符不能重载:

运算符 用途
:: 作用域解析,例如 std::cout
?: 条件运算,例如 condition ? a : b
. 通过对象访问成员,例如 object.member
.* 通过对象与成员指针访问成员,例如 object.*member_pointer

来源:C++ 标准草案:运算符重载。

重载加号运算符

三个类,Dog,Cat,Person。

class Dog
{
public:
    int d;
};

class Cat
{
public:
    int c;
};

class Person
{
public:
    int p;
};

//运算符重载实际上就是一个函数
Cat operator+(const Person& p, const Dog& d)
{
    Cat cat;
    cat.c = p.p + d.d;
    return cat;
}

void testOperator()
{
    Dog d;
    Cat c;
    Person x;

    d.d = 100;
    x.p = 200;

    c = x + d;
    //也可以直接调用
    //c = x.operator+(d);

    cout << c.c << endl;
}

上面的运算符重载函数是个全局函数,也可以做成一个成员函数。

class Person
{
public:
    Cat operator+(const Dog& d)
    {
        Cat cat;
        cat.c = p + d.d;
        return cat;
    }
public:
    int p;
};

例:C++重载字符串加号运算符,拼接字符串。

例:

销售卖书,两个销售一共卖多少,每个销售卖的数量和卖了多少钱不一样。计算一共卖了多少本,一共卖了多少钱。

class Sale
{
    //友元函数 可以访问类中的私有成员
    friend Sale operator+(const Sale &left, const Sale &right);
public:

    /// 构造函数
    /// - Parameters:
    ///   - book: 什么书
    ///   - units: 卖多少本
    ///   - price: 卖多少钱
    Sale(const string &book, unsigned units, double price)
    : name(book),units_sold(units),revenue(units * price)
    {}


    /// 求平均每本多少钱
    double avg_price() const
    {
        return revenue / units_sold;
    }

//成员变量 为了调试,需要改成public
//private:
public:
    string name;
    unsigned units_sold;
    double revenue;
};

//运算符重载函数做成全局的函数
Sale operator+(const Sale &left, const Sale &right)
{
    Sale sale(left);
    sale.units_sold += right.units_sold;
    sale.revenue += right.revenue;
    return sale;
}

//调用
void test()
{
    Sale sale1("C++ Programming",10,50.0);
    Sale sale2("C++ Programming",2,60.0);
    Sale sale3 = sale1 + sale2;
    cout << sale3.units_sold << ", " << sale3.avg_price() << endl;
}

成员函数还是非成员函数

运算符 实现方式
=、()、[]、-> 必须使用成员函数
一元运算符,如 !、~、++、-- 通常使用成员函数
+=、-=、/=、*=、^=、&=、|=、%=、>>=、<<= 通常使用成员函数
其它普通二元运算符,如 +、-、==、<<、>>、->* 通常使用非成员函数;也可以使用成员函数

“必须”是语言要求,“通常”是实现建议。->* 可使用成员函数或非成员函数。以 std::cout << object 形式输出自定义对象时,左操作数是流对象,通常将重载函数实现为非成员函数。

来源:C++ 标准草案:赋值、函数调用、下标、成员访问、普通二元运算符。