再論C++中介面與實現分離的技術

來源:互聯網
上載者:User

    我在今年2月份寫了篇《C++中介面與實現分離的技術》的文章,用一個很簡單的例子說明了在C++中介面與實現分離的好處及實現方法。很榮幸,這篇文章被推薦到了CSDN的首頁並被多家網站轉載。
    可是當時寫那篇文章的時候,沒有考慮到類與類之間的繼承關係。下面我就來具體的談談這個方面。
    還是以上面提到的那篇文章中的例子來說明。
    執行類:
    lxImplement.h檔案內容:

#include "lxTest.h"

class ClxImplement  
{
public:
    ClxImplement();
    ~ClxImplement();

    void DoSomething();

private:
    ClxTest m_lxTest;

    void lxTest();
};

    lxImplement.cpp檔案內容:

#include "lxImplement.h"

ClxImplement::ClxImplement()
{
}

ClxImplement::~ClxImplement()
{
}

void ClxImplement::lxTest()
{
    m_lxTest.DoSomething();
}

void ClxImplement::DoSomething()
{
    lxTest();
}

    介面類:
    lxExp.h檔案內容:

//  前置聲明
class ClxImplement;

class ClxExp  
{
public:
    ClxExp();
    virtual ~ClxExp();

 void DoSomething();

private:
    //  聲明一個類ClxImplement的指標,不需要知道類ClxImplement的定義
    ClxImplement *m_pImpl;
};

  lxExp.cpp檔案內容:

//  在這裡包含類ClxImplement的定義標頭檔
#include "lxImplement.h"

ClxExp::ClxExp()
{
    m_pImpl = new ClxImplement;
}

ClxExp::~ClxExp()
{
    if (m_pImpl)
        delete m_pImpl;
}

void ClxExp::DoSomething()
{
    m_pImpl->DoSomething();
}

    但是,如果類ClxExp是另一個類的子類,而在類ClxExp中要調用基類的方法,那上面的方案就不行了。比如說,類ClxExp的基類是下面的樣子:

class ClxInF
{
public:
    ClxInF();
    virtual ~ClxInF();

    bool InitSet();

    virtual void DoSomething();
};

    相應的類ClxExp的聲明變成了如下的形式:

class ClxExp : public ClxInF
{
public:
    ClxExp();
    virtual ~ClxExp();

    void DoSomething();

private:
    ClxImplement *m_pImpl;
};

   現在, 假設我們必須在類ClxExp的DoSomething()方法中根據InitSet()的傳回值來確定是否執行操作。最簡單的實現方法是把類ClxExp的DoSomething()方法改成下面的樣子:

void ClxExp::DoSomething()
{
    if (InitSet())
        m_pImpl->DoSomething();
}

    可是如果這樣的話,介面與實現就沒有徹底的分離,因為實現細節被暴露到了介面類中。為了避免這種情況發生,我們就必須把對基類ClxInF的方法InitSet()調用放到執行類ClxImplement當中。可是怎麼在執行類ClxImplement當中調用介面類ClxExp的基類ClxInF的方法呢?其實很簡單,因為類ClxExp是類ClxInF的子類,那麼它也就繼承了類ClxInF的方法,只要把類ClxExp的this指標傳給類ClxImplement,就可以通過這個指標來調用類ClxExp的方法,當然也可以調用類ClxExp從基類ClxInF繼承來的方法。下面是修改後的代碼:
    lxImplement.h檔案內容:

#include "lxTest.h"
// 包含聲明類ClxExp的標頭檔
#include "lxExp.h"

class ClxImplement  
{
public:
    //  建構函式,傳入類的ClxExp的指標
    ClxImplement(ClxExp *plxExp);
    ~ClxImplement();

    void DoSomething();

private:
    ClxTest m_lxTest;
    //  定義一個類ClxExp的指標,可以通過該指標調用類ClxExp從基類繼承下來的方法
    ClxExp *m_plxExp;

    void lxTest();
};

    lxImplement.cpp檔案內容:

#include "lxImplement.h"

ClxImplement::ClxImplement(ClxExp *plxExp)
{
    m_plxExp = plxExp;
}

ClxImplement::~ClxImplement()
{
}

void ClxImplement::lxTest()
{
    m_lxTest.DoSomething();
}

void ClxImplement::DoSomething()
{
    if (m_plxExp->InitSet())
        lxTest();
}

    對於類ClxExp來說,只要修改一下它的建構函式就行了,其他都不用修改。

ClxExp::ClxExp()
{
    m_pImpl = new ClxImplement(this);
}

    這樣,我們就解決了前面所提到的問題。
    當然,也許有人會說,讓類ClxImplement也從類ClxInF繼承不是更簡單嗎?那樣就可以在類ClxImplement中直接調用類ClxInF的方法,也不用添加什麼代碼。可是我們知道公有繼承是的子類與基類是IS-A的關係。也就是說子類是一種基類,就像說轎車是一種汽車一樣。可是,在我們例子中,類ClxImplement只是類ClxExp的一個執行類而已,跟類ClxExp的基類ClxInF沒有一點兒關係,更不要說是一種ClxInF了。所以不能讓類ClxImplement從類ClxInF繼承。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.