C和C++的物件導向專題(4)——解決封裝,避免介面

來源:互聯網
上載者:User

標籤:c++   介面   封裝   編譯速度   

本專欄文章列表

一、何為物件導向

二、C語言也能實現物件導向

三、C++中的不優雅特性

四、解決封裝,避免介面

五、合理使用模板,避免代碼冗餘

六、C++也能反射

七、單例模式解決靜態成員對象和全域對象的構造順序難題

八、更為進階的前置處理器PHP

四、解決封裝,避免介面

恩,今天我們來討論,如何通過設計,解決C++中的不優雅特性,改進項目的結構,改善編譯速度。

上次我們提到,如果一個類的封裝不好,容易導致種種不便,那麼如何設計能夠避免這種現象呢?

class test {public:    void print() {        printf("Hello\n");    }    void print2() {        printf("K : %d\n", k);    }private:    int k;};
簡要的改進,將函數的實現移動到類cpp實現檔案中

最簡單的想法就是將實現和聲明分開,這也是C++提倡的,這樣雖然檔案會增多,但編譯速度和代碼的清晰度會提升。

/* test.h */class test {public:    void print();    void print2();private:    int k;};
/* test.cpp */#include "test.h"void test::print() {    printf("Hello\n");}void test::print2() {    printf("K : %d\n", k);}

很明顯的,這樣我們改動cpp檔案中,.h檔案不會受到影響,但假若我的private方法增加了,那麼還是需要改動.h檔案,進而會影響所有引用我的部分,為了避免這種情況出現,有什麼好設計方法嗎?

使用介面降低代碼耦合

一種標準的設計模式是使用介面,這在很多庫的設計時也被經常採用,核心思想是通過多態調用的方式,避免內部方法的暴露。

介面一般就是C++的多態類:

/* Itest.h */class Itest {public:    virtual void print() = 0;    virtual void print2() = 0;};extern ITest* createItest(); // 類似工廠的方式為你構建類
/* Itest.cpp */#include "test.h"ITest* createItest() {    return new test();}

讓test從這個介面繼承出來:

/* test.h */class test : public Itest {public:    virtual void print();    virtual void print2();private:    int k;};

這樣的好處當然十分明顯了,將類轉成介面的形式,就能方便的修改下面的實作類別,無論實作類別如何改動,都在模組範圍內,介面不變。
但這樣做的壞處也很明顯,如果C++大量使用這樣的方式實現內部封裝,那麼很多情況下效率比較低,而且代碼複雜度就上來了,需要添加很多的介面類。

輕便的成員類封裝

下面介紹一種簡單的方式來實作類別封裝性的提升,首先還是看這個test類,我們將其提示為test2:

/* test2.h */class test2 {public:    void print();    void print2();private:    int k;};

這裡的k實際上並不需要寫在這裡,我們需要的是將private的部分整體的封裝成一個類:

/* test2.h */class test2_private;class test2 {public:    test2();    test2(int);    ~test2();    void print();    void print2();protected:    test2_private* that;};
/* test2.cpp */#include "test2.h"class test2_private {public:    int k;};test2::test2() {    that = new test2_private();    that->k = 0;}test2::test2(int k) {    that = new test2_private();    that->k = k;}test2::~test2() {    delete that;}

這時我們發現,這種封裝可以很有效解決類的介面不便的問題,而由於只使用了類指標,所以我們並不需要前向聲明這個私人類,於是這個類可以方便的被修改,從而避免了介面和多態調用的問題。

這種設計還有一個用途,假若你有另外的代碼產生器產生的程式碼,需要和已有的類嵌入使用,那麼推薦使用這種方式,Qt中就是這樣做的:

#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>namespace Ui {class MainWindow;}class MainWindow : public QMainWindow{    Q_OBJECTpublic:    explicit MainWindow(QWidget *parent = 0);    ~MainWindow();private:    Ui::MainWindow *ui;};#endif // MAINWINDOW_H
#include "mainwindow.h"#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :    QMainWindow(parent),    ui(new Ui::MainWindow){    ui->setupUi(this);}MainWindow::~MainWindow(){    delete ui;}

我們發現這裡有一個神奇的代碼

namespace Ui {class MainWindow;}

其實這隻是另外一個類,和本類並不同名,Ui::MainWindow是qt設計器幫忙產生的類,用來標註UI介面產生的一些代碼,為了讓代碼很好的和我們自己的類統一起來,他們用了這種方式。

C和C++的物件導向專題(4)——解決封裝,避免介面

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.