C++中接口與實現的分離技術

<pre name="code" class="cpp"> 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繼承。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章