深入理解C語言11 基於對象(Object based)編程

在使用對象編程之前先要了解什麼是對象。

對象是指對數據和操作的抽象封裝。


優點:

高內聚, 使用方便

缺點:

相關的操作函數是有狀態的(也就是函數編程裏常說的副作用, 操作系統開發裏的不可重入函數),

 不同時間點執行該函數,有可能會返回不同的結果), 不方便並行處理


C語言要實現一個對象,關鍵是解決數據和操作的封裝。


1> 數據的封裝主要是通過結構體來實現, 操作的封裝則是通過函數指針來實現。

2> 數據隱藏, 主要是通過萬能的void* 指針來實現。


對象的通用操作主要有以下3個

1> 創建, 對應new函數

2> 銷燬, 對應delete函數

3> 複製, 對應clone函數


C語言並不支持 字符串轉變量功能, RTTI需要自己加type屬性,並實現相應的工廠類。

以FFMPEG的URLProtocol類爲例:

typedef struct URLProtocol {
    const char *name;
    int     (*url_open)( URLContext *h, const char *url, int flags);
    
    /**
     * Read data from the protocol.
     * If data is immediately available (even less than size), EOF is
     * reached or an error occurs (including EINTR), return immediately.
     * Otherwise:
     * In non-blocking mode, return AVERROR(EAGAIN) immediately.
     * In blocking mode, wait for data/EOF/error with a short timeout (0.1s),
     * and return AVERROR(EAGAIN) on timeout.
     * Checking interrupt_callback, looping on EINTR and EAGAIN and until
     * enough data has been read is left to the calling function; see
     * retry_transfer_wrapper in avio.c.
     */
    int     (*url_read)( URLContext *h, unsigned char *buf, int size);
    int     (*url_write)(URLContext *h, const unsigned char *buf, int size);
    int64_t (*url_seek)( URLContext *h, int64_t pos, int whence);
    int     (*url_close)(URLContext *h);
    ...
    int priv_data_size;
    const AVClass *priv_data_class;
    int flags;
    int (*url_check)(URLContext *h, int mask);
} URLProtocol;


上面的url_open等便對應一系列操作接口。


接下來看如何構建對象實例

URLProtocol ff_tcp_protocol = {
    .name                = "tcp",
    .url_open            = tcp_open,
    .url_read            = tcp_read,
    .url_write           = tcp_write,
    .url_close           = tcp_close,
    .url_get_file_handle = tcp_get_file_handle,
    .url_shutdown        = tcp_shutdown,
    .priv_data_size      = sizeof(TCPContext),
    .priv_data_class     = &tcp_context_class,
    .flags               = URL_PROTOCOL_FLAG_NETWORK,
};


這裏的Tcp便是抽象URLProtocol的一個具體實例。


操作函數的實現如下:

int tcp_open(URLContext *h, const char *uri, int flags)
{

}

需要注意的是,由於URLContext 裏面封裝了URLProtocol指針,我們並沒有加URLProtocol* this指針。


與C++、Java等語法層面支持類語言不同,我們需要稍微做一些編譯器做的事情,自己手動將操作與數據綁定。

如果覺得自己加this指針很麻煩, 可以用C語言提供的宏,或Perl、Python等腳本語言做自動代碼生成,來提高效率。







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