小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

請謹(jǐn)慎實(shí)現(xiàn)operator==操作符函數(shù)

 win2zhang 2014-10-21

c++中,==操作符是很有用的,但是它的實(shí)現(xiàn)也并非想象中的那樣容易。本文將圍繞一個簡單的c++例子程序展開討論,以便尋求一個簡單的解決方法。

在開始講述等于操作符之前,我們先了解一下涉及的類定義。第一個類是一個一維點(diǎn)定義,很簡單。一個構(gòu)造器和析構(gòu)器,一個operator==操作符。

Definition of Class Point1D

class Point1D

{

protected:

    int xPos;

   

public:

    Point1D( int x = 0 )

        : xPos( x )

    {

    }

 

    virtual ~Point1D()

    {

    }

   

    inline bool operator==( const Point1D &rhs )

    {

        return xPos == rhs.xPos;

    }

};

第二個類是Piont2D,它是一個二維點(diǎn),y軸被使用來確認(rèn)相應(yīng)位置。

class Point2D : public Point1D

{

protected:

    int yPos;

   

public:

    Point2D( int x = 0, int y = 0 )

        : Point1D( x ), yPos( y )

    {

    }

   

    virtual ~Point2D()

    {

    }

   

    inline bool operator==( const Point2D &rhs )

    {

        return (this == &rhs) || (xPos == rhs.xPos && yPos == rhs.yPos);

    }

};

從上面來看,兩個類好像都定義的很好,真的是這樣嗎?讓我運(yùn)行一下看看結(jié)果吧。

#include <iostream>

using namespace std;


int main( void )

{

    Point1D p1d( 10 );

    Point2D p2d( 10, 20 );

    Point2D p2d2( 10, 30 );

    Point1D *pp2d1 = &p2d;

    Point1D *pp2d2 = &p2d2;

 

    if ( p1d == p2d )

        cout << "P1D is equal to P2D" << endl;

    else

        cout << "P1D is unequal to P2D" << endl;

 

    if ( *pp2d1 == *pp2d2 )

        cout << "P2D is equal to P2D2" << endl;

    else

        cout << "P2D is unequal to P2D2" << endl;

    return 0;

}

Result:

P1D is equal to P2D

P2D is equal to P2D2

WOW,居然P1DP2D是一樣,P2DP2D2也是一樣。顯然是一個錯誤!錯誤的原因在于我們錯誤的實(shí)現(xiàn)了Point1Doperator==操作符。它沒有對它的子類進(jìn)行有效的檢查。此外,即使Point2D也重載了==操作符,也沒有使P2DP2D2能夠正確的比較。其實(shí),在多態(tài)的環(huán)境中,對于Point2D的操作符的重載往往是沒有用處的,上面就是一個很好的例子。

我們現(xiàn)在遇到的問題是:

1)如何在Point1D中有效的對它的子類進(jìn)行檢查呢?

2)如何實(shí)現(xiàn)子類中的操作符比較函數(shù)?

對于1),我們沒有辦法判斷,因?yàn)楦割惖膶?shí)現(xiàn)代碼中是無法預(yù)測子類的。有人可能會說為什么不把Point1D中的operator==聲明為virtual類型,然后在子類中重置呢?它的實(shí)現(xiàn)代碼可能類似于這樣:

    virtual bool operator==( const Point1D &rhs )

    {

        const Point2D *pp2d = dynamic_cast<const Point2D *>( &rhs );

        if ( pp2d == NULL )

            return false;

        if ( this == pp2d )

            return true;

        return xPos == pp2d->xPos && yPos == pp2d->yPos;

    }  

 

到現(xiàn)在為止看上去好像是一個很好的主意,這樣可以在使用==的時候時候清楚的識別子父類。真的是這樣嗎?請看下面測試結(jié)果J.

#include <iostream>

using namespace std;


int main( void )

{

    Point1D p1d( 10 );

    Point2D p2d( 10, 20 );

    Point2D p2d2( 10, 30 );

    Point1D *pp2d1 = &p2d;

    Point1D *pp2d2 = &p2d2;

 

    if ( p1d == p2d )

        cout << "P1D is equal to P2D" << endl;

    else

        cout << "P1D is unequal to P2D" << endl;

 

    if ( p2d == p1d )

        cout << "P2D is equal to P1D" << endl;

    else

        cout << "P2D is unequal to P1D" << endl;

 

    if ( *pp2d1 == *pp2d2 )

        cout << "P2D is equal to P2D2" << endl;

    else

        cout << "P2D is unequal to P2D2" << endl;

   

    return 0;

}

Result:

P1D is equal to P2D

P2D is unequal to P1D

P2D is unequal to P2D2

對于Point2D之間的比較我們很好的解決了,但是對于P1DP2D之間的比較居然出現(xiàn)了戲劇性的自相矛盾!仔細(xì)研究代碼后,我們發(fā)現(xiàn)問題還是出在Point1D==操作符上,我們依然沒有能夠合適的識別子父類。如何解決呢?對于A=B成立的話,我們一定可以獲得B=A也成立,所以我們在做Point1D==操作符的時候,一定要做兩次判斷等于判斷,即A == B && B == A. 請看下列代碼.

    virtual bool operator==( const Point1D &rhs )

    {

        return xPos == rhs.xPos && *const_cast<Point1D *>( &rhs ) == *this;

    }

Ok,讓我們再次運(yùn)行測試代碼把。

Result:

P1D is unequal to P2D

P2D is unequal to P1D

P2D is unequal to P2D2

非常好,好象我們把問題解決了,是嗎?Point1D的問題解決了,但是Point2D呢?它也存在這樣的問題,我的天,這樣蹩腳的代碼還要在Point2D中重寫一次!我簡直要發(fā)瘋了!難道日后所有的子類都要這樣嗎??。?!有沒有解決方法?不要太著急,我們可以很簡單的處理它。請看下面完整代碼.

#include <iostream>

using namespace std;


class Point1D

{

protected:

    int xPos;

 

    virtual bool equalTo( const Point1D &rhs ) const

    {

        return xPos == rhs.xPos;

    }

   

public:

    Point1D( int x = 0 )

        : xPos( x )

    {

    }

 

    virtual ~Point1D()

    {

    }

   

    inline bool operator==( const Point1D &rhs )

    {

        return equalTo( rhs ) && rhs.equalTo( *this );

    }

   

};

 

class Point2D : public Point1D

{

protected:

    int yPos;

   

    virtual bool equalTo( const Point1D &rhs ) const

    {

        const Point2D *pp2d = dynamic_cast<const Point2D *>( &rhs );

        if ( pp2d == NULL )

            return false;

        if ( this == pp2d )

            return true;

        return yPos == pp2d->yPos && Point1D::equalTo( rhs );

    }  

 

public:

    Point2D( int x = 0, int y = 0 )

        : Point1D( x ), yPos( y )

    {

    }

   

    virtual ~Point2D()

    {

    }  

};

 

 

int main( void )

{

    Point1D p1d( 10 );

    Point2D p2d( 10, 20 );

    Point2D p2d2( 10, 30 );

    Point1D *pp2d1 = &p2d;

    Point1D *pp2d2 = &p2d2;

 

    if ( p1d == p2d )

        cout << "P1D is equal to P2D" << endl;

    else

        cout << "P1D is unequal to P2D" << endl;

 

    if ( p2d == p1d )

        cout << "P2D is equal to P1D" << endl;

    else

        cout << "P2D is unequal to P1D" << endl;

 

    if ( *pp2d1 == *pp2d2 )

        cout << "P2D is equal to P2D2" << endl;

    else

        cout << "P2D is unequal to P2D2" << endl;

   

    return 0;

}

Result:

P1D is unequal to P2D

P2D is unequal to P1D

P2D is unequal to P2D2

我們使用了equalTo函數(shù)來完成了A==B&&B==A的雙向比較,在equalTo中,實(shí)現(xiàn)的方法和以前的完全一致,不關(guān)心比較的對象是否是父子關(guān)系。對于子類,我們僅僅重置equalTo方法就能夠正確地實(shí)現(xiàn)了operator==方法,相當(dāng)?shù)某錾皇菃???/span>J

這樣做的好處主要體現(xiàn)在以下幾點(diǎn):

1)能夠在子類中正確地實(shí)現(xiàn)operator==方法,只要重置對應(yīng)的equalTo就可以了。

2operator==沒有使用virtual修飾,WOW,長出了一口氣,對于它的很多注意點(diǎn)終于可以解脫了。

3)也無需為蹩腳的virtual operator==感到傷心了,因?yàn)楫吘鼓菢幼霾⒎鞘钦嬲饬x上的子類==操作符。Point2D中的操作符參數(shù)應(yīng)該是Point2D,而非Point1D,難道不是嗎J!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多