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
擦,怎么结果输出不一样了!这是神马原因(自己想想看吧)?
所以,这里是本文要强调的一点,看似很简单的操作符重载,但是如果掉以轻心,往往结果会出人意料。
要解决这个问题,有两种方法:
- 将操作符重载成virtual类型
- 使用虚函数代替操作符重载
posted on 2012-04-14 20:33 wpcockroach 阅读(370) 评论(0) 编辑 收藏 举报