【C++】 运算符重载

1、一元运算符

运算符重载是C++的一大特色,以函数重载的形式出现,函数名为关键字operator后跟着一个运算符,这些函数可以作为类的成员函数实现,也可以作为类的友元函数以全局函数的形式实现,而有的操作符只能以其中一种方式实现,因为全局函数没有this指针,所以在参数列表中比成员函数多一个参数。可以重载的一元运算符包括+-~&!++--,例子如下。

// Overloading Unary Operators
// Non-member functions
class Integer {
    long i;
    Integer* This() { return this; }
public:
    Integer(long ll = 0) : i(ll) {}
    // No side effects takes const& arguments
    friend const Integer& operator+(const Integer& a);
    friend const Integer operator-(const Integer& a);
    friend const Integer operator~(const Integer& a);
    friend Integer* operator&(Integer& a);
    friend int operator!(const Integer& a);
    // Side effects have non-const& argument
    // Prefix
    friend const Integer& operator++(Integer& a);
    // Postfix
    friend const Integer operator++(Integer& a, int);
    // Prefix
    friend const Integer& operator--(Integer& a);
    // Postfix
    friend const Integer operator--(Integer& a, int);
};
// Global operators
const Integer& operator+(const Integer& a) {
    return a; // Unary + has no effect
}
const Integer operator-(const Integer& a) {
    return Integer(-a.i);
}
const Integer operator~(const Integer& a) {
    return Integer(~a.i);
}
Integer* operator&(Integer& a) {
    return a.This(); // &a is recursive!
}
int operator!(const Integer& a) {
    return !a.i;
}
// Prefix; return incremented value
const Integer& operator++(Integer& a) {
    a.i++;
    return a;
}
// Postfix; return the value before increment:
const Integer operator++(Integer& a, int) {
    Integer before(a.i);
    a.i++;
    return before;
}
// Prefix; return decremented value
const Integer& operator--(Integer& a) {
    a.i--;
    return a;
}
// Postfix; return the value before decrement:
const Integer operator--(Integer& a, int) {
    Integer before(a.i);
    a.i--;
    return before;
}
// Member functions (implicit "this")
class Byte {
    unsigned char b;
public:
    Byte(unsigned char bb = 0) : b(bb) {}
    // No side effects: const member function
    const Byte& operator+() const {
        return *this;
    }
    const Byte operator-() const {
        return Byte(-b);
    }
    const Byte operator~() const {
        return Byte(~b);
    }
   Byte operator!() const {
        return Byte(!b);
    }
    Byte* operator&() {
        return this;
    }
    // Side effects: non-const member function
    const Byte& operator++() { // Prefix
        b++;
        return *this;
    }
    const Byte operator++(int) { // Postfix
        Byte before(b);
        b++;
        return before;
    }
    const Byte& operator--() { // Prefix
        b--;
        return *this;
    }
    const Byte operator--(int) { // Postfix
        Byte before(b);
        b--;
        return before;
    }
};

2、二元运算符

可以重载的二元运算符包括+-*/%^&|<<>>+=-=*=/=%=^=&=|=<<=>>=,例子如下。二元运算符一般使用非成员函数。

// Overloading Binary Operators
// Non-member overloaded operators
// Non-member functions
class Integer {
    long i;
public:
    Integer(long ll = 0) : i(ll) {}
    // Operators that create new, modified value
    friend const Integer operator+(const Integer& left, const Integer& right);
    friend const Integer operator-(const Integer& left, const Integer& right);
    friend const Integer operator*(const Integer& left, const Integer& right);
    friend const Integer operator/(const Integer& left, const Integer& right);
    friend const Integer operator%(const Integer& left, const Integer& right);
    friend const Integer operator^(const Integer& left, const Integer& right);
    friend const Integer operator&(const Integer& left, const Integer& right);
    friend const Integer operator|(const Integer& left, const Integer& right);
    friend const Integer operator<<(const Integer& left, const Integer& right);
    friend const Integer operator>>(const Integer& left, const Integer& right);
    // Assignments modify & return lvalue
    friend Integer& operator+=(Integer& left, const Integer& right);
    friend Integer& operator-=(Integer& left, const Integer& right);
    friend Integer& operator*=(Integer& left, const Integer& right);
    friend Integer& operator/=(Integer& left, const Integer& right);
    friend Integer& operator%=(Integer& left, const Integer& right);
    friend Integer& operator^=(Integer& left, const Integer& right);
    friend Integer& operator&=(Integer& left, const Integer& right);
    friend Integer& operator|=(Integer& left, const Integer& right);
    friend Integer& operator<<=(Integer& left, const Integer& right);
    friend Integer& operator>>=(Integer& left, const Integer& right);
    // Conditional operators return true/false
    friend int operator==(const Integer& left, const Integer& right);
    friend int operator!=(const Integer& left, const Integer& right);
    friend int operator<(const Integer& left, const Integer& right);
    friend int operator>(const Integer& left, const Integer& right);
    friend int operator<=(const Integer& left, const Integer& right);
    friend int operator>=(const Integer& left, const Integer& right);
    friend int operator&&(const Integer& left, const Integer& right);
    friend int operator||(const Integer& left, const Integer& right);
};
// Implementation of overloaded operators
const Integer operator+(const Integer& left, const Integer& right) {
    // Integer tmp(left.i + right.i); // 调用构造函数创建tmp对象
    // return tmp; // 调用拷贝构造函数把tmp拷贝到外部返回值的存储单元 调用析构函数销毁tmp对象
    return Integer(left.i + right.i); // 返回值优化 返回临时对象告诉编译器直接把这个对象创建在外部返回值的存储单元里
}
const Integer operator-(const Integer& left, const Integer& right) {
    return Integer(left.i - right.i);
}
const Integer operator*(const Integer& left, const Integer& right) {
    return Integer(left.i * right.i);
}
const Integer operator/(const Integer& left, const Integer& right) {
    return Integer(left.i / right.i); // right.i != 0
}
const Integer operator%(const Integer& left, const Integer& right) {
    return Integer(left.i % right.i); // right.i != 0
}
const Integer operator^(const Integer& left, const Integer& right) {
    return Integer(left.i ^ right.i);
}
const Integer operator&(const Integer& left, const Integer& right) {
    return Integer(left.i & right.i);
}
const Integer operator|(const Integer& left, const Integer& right) {
    return Integer(left.i | right.i);
}
const Integer operator<<(const Integer& left, const Integer& right) {
    return Integer(left.i << right.i);
}
const Integer operator>>(const Integer& left, const Integer& right) {
    return Integer(left.i >> right.i);
}
// Assignments modify & return lvalue
Integer& operator+=(Integer& left, const Integer& right) {
    if(&left == &right) {/* self-assignment*/}
    left.i += right.i;
    return left;
}
Integer& operator-=(Integer& left, const Integer& right) {
    if(&left == &right) {/* self-assignment*/}
    left.i -= right.i;
    return left;
}
Integer& operator*=(Integer& left, const Integer& right) {
    if(&left == &right) {/* self-assignment*/}
    left.i *= right.i;
    return left;
}
Integer& operator/=(Integer& left, const Integer& right) {
    // right.i != 0
    if(&left == &right) {/* self-assignment*/}
    left.i /= right.i;
    return left;
}
Integer& operator%=(Integer& left, const Integer& right) {
    // right.i != 0
    if(&left == &right) {/* self-assignment*/}
    left.i %= right.i;
    return left;
}
Integer& operator^=(Integer& left, const Integer& right) {
    if(&left == &right) {/* self-assignment*/}
    left.i ^= right.i;
    return left;
}
Integer& operator&=(Integer& left, const Integer& right) {
    if(&left == &right) {/* self-assignment*/}
    left.i &= right.i;
    return left;
}
Integer& operator|=(Integer& left, const Integer& right) {
    if(&left == &right) {/* self-assignment*/}
    left.i |= right.i;
    return left;
}
Integer& operator<<=(Integer& left, const Integer& right) {
    if(&left == &right) {/* self-assignment*/}
    left.i <<= right.i;
    return left;
}
Integer& operator>>=(Integer& left, const Integer& right) {
    if(&left == &right) {/* self-assignment*/}
    left.i >>= right.i;
    return left;
}
// Conditional operators return true/false
int operator==(const Integer& left, const Integer& right) {
    return left.i == right.i;
}
int operator!=(const Integer& left, const Integer& right) {
    return left.i != right.i;
}
int operator<(const Integer& left, const Integer& right) {
    return left.i < right.i;
}
int operator>(const Integer& left, const Integer& right) {
    return left.i > right.i;
}
int operator<=(const Integer& left, const Integer& right) {
    return left.i <= right.i;
}
int operator>=(const Integer& left, const Integer& right) {
    return left.i >= right.i;
}
int operator&&(const Integer& left, const Integer& right) {
    return left.i && right.i;
}
int operator||(const Integer& left, const Integer& right) {
    return left.i || right.i;
}
// Member overloaded operators
// Member functions (implicit "this")
class Byte {
    unsigned char b;
public:
    Byte(unsigned char bb = 0) : b(bb) {}
    const Byte operator+(const Byte& right) const {
        return Byte(b + right.b);
    }
    const Byte operator-(const Byte& right) const {
        return Byte(b - right.b);
    }
    const Byte operator*(const Byte& right) const {
        return Byte(b * right.b);
    }
    const Byte operator/(const Byte& right) const {
        return Byte(b / right.b); // right.b != 0
    }
    const Byte operator%(const Byte& right) const {
        return Byte(b % right.b); // right.b != 0
    }
    const Byte operator^(const Byte& right) const {
        return Byte(b ^ right.b);
    }
    const Byte operator&(const Byte& right) const {
        return Byte(b & right.b);
    }
    const Byte operator|(const Byte& right) const {
        return Byte(b | right.b);
    }
    const Byte operator<<(const Byte& right) const {
        return Byte(b << right.b);
    }
    const Byte operator>>(const Byte& right) const {
        return Byte(b >> right.b);
    }
    // Assignments modify & return lvalue.
    // operator= can only be a member function
    Byte& operator=(const Byte& right) {
        // Handle self-assignment
        if(this == &right) return *this;
        b = right.b;
        return *this;
    }
    Byte& operator+=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b += right.b;
        return *this;
    }
    Byte& operator-=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b -= right.b;
        return *this;
    }
    Byte& operator*=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b *= right.b;
        return *this;
    }
    Byte& operator/=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b /= right.b; // right.b != 0
        return *this;
    }
    Byte& operator%=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b %= right.b; // right.b != 0
        return *this;
    }
    Byte& operator^=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b ^= right.b;
        return *this;
    }
    Byte& operator&=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b &= right.b;
        return *this;
    }
    Byte& operator|=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b |= right.b;
        return *this;
    }
    Byte& operator<<=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b <<= right.b;
        return *this;
    }
    Byte& operator>>=(const Byte& right) {
        if(this == &right) {/* self-assignment */}
        b >>= right.b;
        return *this;
    }
    // Conditional operators return true/false:
    int operator==(const Byte& right) const {
        return b == right.b;
    }
    int operator!=(const Byte& right) const {
        return b != right.b;
    }
    int operator<(const Byte& right) const {
        return b < right.b;
    }
    int operator>(const Byte& right) const {
        return b > right.b;
    }
    int operator<=(const Byte& right) const {
        return b <= right.b;
    }
    int operator>=(const Byte& right) const {
        return b >= right.b;
    }
    int operator&&(const Byte& right) const {
        return b && right.b;
    }
    int operator||(const Byte& right) const {
        return b || right.b;
    }
};

3、下标运算符

下标运算符[],行为像数组一样,必须是成员函数,只接受一个参数。

class ByteArray
{
public:
    char operator[](int i) const;
};

4、new和delete

运算符new和delete也可以进行重载,全局函数或者成员函数,用于控制动态存储分配,不过一般不这么做。

void* operator new(std::size_t)
void* operator new[](std::size_t);
void operator delete(void*);
void operator delete[](void*);
inline void* operator new(std::size_t, void *p) { return p; }
inline void* operator new[](std::size_t, void *p) { return p; }
inline void operator delete(void*, void*) {}
inline void operator delete[](void*, void*) {}

5、逗号

当逗号出现在一个对象左右,而该对象的类型是逗号定义所支持的类型时,将调用逗号运算符,然后,调用的目标不是函数参数表,而是被逗号分隔开的、没有被括号括起来的对象,除了使语言保持一致性外,这个运算符似乎没有许多实际用途。

class After
{
pubic:
    const After& operator,(const After&) const { return *this; }
};
class Before {};
Before& operator,(int, Before &b) { return b; }
void test()
{
    After a, b;
    a, b; // operator, called
    Before c;
    1, c; // operator, called
}

6、指针

下面是几个特殊的可重载运算符。当希望一个对象表现的像一个指针时,通常就要用到指针间接引用运算符operator->,它是个成员函数,由于这样一个对象比一般的指针有着更多与生俱来的灵巧性,于是常被称作为灵巧指针。

class Object {};
class ObjectContainer
{
public:
    vector<Object*> objs;
};
class SmatrPointer
{
pubic:
    Object* operator->() const { return oc.objs[index]; }
private:
    ObjectContainer &oc;
    int index;
};

另外,运算符operator->*用于成员指针;operator()是个多功能函数,参数不受限制,可以实现任意特定的功能;括号运算符进行类型转换时格式为operator Type(),它们都是成员函数。在类型转换中,有时会通过构造函数自动进行类型转换,这可能会有问题,解决方法是在构造函数前面使用explicit关键字。

class Dog()
{
public:
    int run(int i) const { return i; }
    typedef int (Dog::*PMF)(int) const;
    class FuncObj
    {
    public:
        FuncObj(Dog *dog, PMF pmf) : ptr(dog), pmem(pmf) {}
        int operator()(int i) const { return (ptr->*pmem)(i); }
    private:
        Dog *ptr;
        PMF pmem;
    };
    FuncObj operator->*(PMF pmf)
    {
        return FuncObj(this, pmf);
    } 
}
void test()
{
    Dog d;
    Dog::PMF pmf = &Dog::run;
    (d->*pmf)(1);
}

Class A()
{
public:
    A(B* bb) : b(bb) {}
private:
    B* b;
};
Class B()
{
public:
    operator A() const { return A(this); } // B转换为A
};

7、输入输出

输入输出运算符operator>>operator<<作为全局函数,可以自定义任何想要的结果。

class Integer
{
    friend ostream& operator<<(ostream& os, const Integer &r);
    friend istream& operator>>(istream& is, Inteter &r);
    int num;
};
ostream& operator<<(ostream& os, const Integer &r)
{
    os << r.num;
    os << endl;
    return os;
}
istream& operator>>(istream& is, Inteter &r)
{
    is >> r.num;
    return is;
}

8、不能重载的运算符

在可用的运算符集合里,存在一些不能重载的运算符,如下。

operator.
operator.*
user custom operator
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值