本專欄文章列表
一、何為面向對象
二、C語言也能實現面向對象
三、C++中的不優雅特性
四、解決封裝,避免接口
五、合理使用模板,避免代碼冗余
六、C++也能反射
七、單例模式解決靜態成員對象和全局對象的構造順序難題
八、更為高級的預處理器PHP
今天要為大家介紹C語言的面向對象設計方法,正如題記上面所說,面向對象是一種思想,而並非是一種語言,我們將會介紹C語言實現的面向對象開發方式。
眾所周知,C++中的面向對象十分方便,但在C中,並沒有類,但我們可以通過C的結構體來實現,然後,手動將this指針傳入
目前這個方法,應該是C語言設計中,簡便易用的方式,而且能較好的體現面向對象的設計思路,然而遺憾的是,沒有繼承和多態。
例如,我們這樣一個C++類
class test {
public:
test(char* str, int k) {
this->str = str;
this->k = k;
}
void ShowMessage() {
for (int i = 0; i < k; ++i)
printf("%s\n", str);
}
private:
int k;
char* str;
};
那麼我們可以這樣轉換為一個C類
/* test.h */
typedef struct _test {
int k;
char* str;
} test;
test* TestCreate();
void ShowMessage(test*);
/* test.c */
test* TestCreate() {
return (test*) malloc(sizeof(test));
}
void ShowMessage(test* t) {
int i;
for (i = 0; i < t->k; ++i) {
printf("%s\n", t->str);
}
}
其實思路也很清晰,思路簡單易懂,實現也很清新明快,在各類C工程中使用極為廣泛。
如果你希望學習C語言的GUI程序設計,那麼,必定要學習的就是GObject的類實現方式。
GObject相當於從C層面上模擬了一個C++的類對象模型,實現當然相對復雜的多。
下面我們來實際看一下一個GTK的窗口類,這是GTK+-3.0的一段樣例:
/* appwin.h */
#ifndef APPWIN_H
#define APPWIN_H
#include "app.h"
#include
/* 該類的類型定義以及類型轉換宏 */
#define APP_WINDOW_TYPE (app_window_get_type())
#define APP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APP_WINDOW_TYPE, AppWindow))
/* 該類分成兩部分,一部分是成員,一部分是類本身 */
typedef struct _AppWindow AppWindow;
typedef struct _AppWindowClass AppWindowClass;
GType app_window_get_type (void);
AppWindow* app_window_new (App *app);
void app_window_open (AppWindow *win, GFile *file);
#endif // APPWIN_H
而其真實的定義是在.c文件中
struct _AppWindow
{
GtkApplicationWindow parent;
};
struct _AppWindowClass
{
GtkApplicationWindowClass parent_class;
};
typedef struct _AppWindowPrivate AppWindowPrivate;
struct _AppWindowPrivate
{
GSettings *settings;
GtkWidget *stack;
GtkWidget *search;
GtkWidget *searchbar;
GtkWidget *searchentry;
GtkWidget *gears;
GtkWidget *sidebar;
GtkWidget *words;
GtkWidget *lines;
GtkWidget *lines_label;
};
G_DEFINE_TYPE_WITH_PRIVATE(AppWindow, app_window, GTK_TYPE_APPLICATION_WINDOW);
/* 後面有具體的實現方法,這裡就不一一列舉 */
我們發現,這種定義方式比C++中的其實更有優勢,封裝的更加徹底。為何這樣說呢?首先,我們的聲明文件十分的簡潔,如果公開方法不修改的話,那麼將其余內容如何改動,都不會影響我們的外部接口。
其次,由於需要顯示的向GObject注冊,那麼動態進行類注冊就成為可能,這樣的設計優勢表現在哪裡呢?多語言的互通性就很好了,因為很多動態語言,是支持類的動態加載以及反射加載的。
另外,vala語言就是基於GObject類型的,他是一門新興的編譯時語言,但其也有很多動態語言的特性,用其開發gtk程序,比C具有明顯的優勢。