C++操作符重载

    操作符重载可以说是C++或者说其他面向对象语言的一个很重要的特性。它可以让对象的相关操作看起来和基本数据类型的操作一样。但是本文的重点不是介绍C++操作符重载的语法和简单的应用,而是要强调一下在应用操作符重载时,你是否真的想清楚了。什么意思呢,且看下文。

    我们假定有下面这些代码:

class CObject
{
public:
    CObject(int iObject = 0) : m_iObject(iObject) {}
    virtual ~CObject() {}

public:
    bool operator ==(const CObject& rhs);

protected:
    // member variables
    int m_iObject;
};

class CCpp : public CObject
{
public:
    CCpp(int iObject, int iCpp = 1) : CObject(iObject), m_iCpp(iCpp) {}
 
public:
    bool operator ==(const CObject& rhs);
    bool operator ==(const CCpp& rhs);

protected:
    // CCpp's member variables
    int m_iCpp;
};

class CJava : public CObject
{
public:
    CJava(int iObject, int iJava = 2) : CObject(iObject), m_iJava(iJava) {}
 
public:
    bool operator ==(const CObject& rhs);
    bool operator ==(const CJava& rhs);

protected:
    // CJava's member variables
    int m_iJava;
};

    可以看到,CObject基类和两个派生类CCpp和CJava,都声明了比较操作符==。下面我们把这几个比较操作符的定义用简单的几句话来实现下:

bool CObject::operator ==(const CObject& rhs)
{
    return m_iObject == rhs.m_iObject;
}

bool CCpp::operator ==(const CObject& rhs)
{
    const CCpp* pCpp = dynamic_cast<const CCpp*>(&rhs);
    if (nullptr == pCpp) { return false; }

    return (*this) == (*pCpp);
}

bool CCpp::operator ==(const CCpp& rhs)
{
    return m_iObject == rhs.m_iObject && m_iCpp == rhs.m_iCpp;
}

bool CJava::operator ==(const CObject& rhs)
{
    const CJava* pJava = dynamic_cast<const CJava*>(&rhs);
    if (nullptr == pCpp) { return false; }

    return (*this) == (*pJava);
}

bool CJava::operator ==(const CJava& rhs)
{
    return m_iObject == rhs.m_iObject && m_iJava == rhs.m_iJava;
}    

    废话不多说,我们直接来看下如何在main函数里用这些函数:

int main()
{
    CObject obj(2);
    CCpp cpp(2, 3);
    CJava java(2);

    if (obj == cpp) { printf("obj == cpp\n"); }  // 注意obj和cpp顺序
    else { printf("obj != cpp\n"); }

    if (cpp == java) { printf("cpp == java\n"); }
    else { printf("cpp != java\n"; }

    return 0;
}

    显而易见,输出的结果应该是:

obj == cpp

cpp != java

    写到这里,终于把引子写完了,废话多啊。下面进入正题了。我们知道,在C++项目中,像这样使用基类和派生类是很少见的,因为我们喜欢用多态。那么,我们的类中总是会存在一些虚函数。因此上面的代码可能会以下面这种形式出现:

int main()
{
    CObject *pObj = nullptr, *pCpp = nullptr, *pJava = nullptr;

    pObj = new CObject(2);
    pCpp = new CCpp(2, 3);
    pJava = new CJava(2);

    if (*pObj == *pCpp) { printf("*pObj == *pCpp\n"); }
    else { printf("*pObj != *pCpp\n"); }

    if (*pCpp == *pJava) { printf("*pCpp == *pJava\n"); }
    else { printf("*pCpp != *pJava\n"); }
}

    运行下看看:

*pObj == *pCpp

*pCpp == *pJava

    擦,怎么结果输出不一样了!这是神马原因(自己想想看吧Smile)?

    所以,这里是本文要强调的一点,看似很简单的操作符重载,但是如果掉以轻心,往往结果会出人意料。

    要解决这个问题,有两种方法:

    1. 将操作符重载成virtual类型
    2. 使用虚函数代替操作符重载
原文地址:https://www.cnblogs.com/wpcockroach/p/2447538.html