zoukankan      html  css  js  c++  java
  • 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. 使用虚函数代替操作符重载
  • 相关阅读:
    初涉SQL Server性能问题(2/4):列出等待资源的会话
    初涉SQL Server性能问题(1/4):服务器概况
    分享
    React Native 自定义radio 单选or多选
    css之定位
    小小小小小小之新闻案例
    paddingmargin的属性与连写
    css标准流和浮动
    css 伪类
    css元素的显示方式
  • 原文地址:https://www.cnblogs.com/wpcockroach/p/2447538.html
Copyright © 2011-2022 走看看