C 程式設計/GObject
由於 C 程式語言不是為面向物件程式設計而建立的,因此它沒有對類、繼承、多型和其他面向物件概念的明確支援。它也沒有自己的虛擬表,這在像 C++、Java 和 C# 這樣的面嚮物件語言中被找到。因此,僅使用 C 的語言特性和標準庫來實現面向物件程式設計正規化可能並不容易。但是,可以透過使用包含函式指標和資料的結構,例如,或者使用第三方庫來實現。
有很多第三方庫旨在為 C 中的面向物件程式設計提供支援。其中最通用的也是最廣泛使用的庫是 GObject 系統,它是 Glib 的一部分。GObject 系統自帶虛擬表。要使用 GObject 系統在 C 中建立一個物件,它必須從 GObject 結構體中進行子類化。
在這個例子中,一個新的物件將被直接實現,並從 GObject 派生。為了簡單起見,該物件被命名為MyObject。
要建立一個簡單的不可派生(最終)物件,必須宣告兩個結構體,例項和類。它們使用宏宣告
/* in myobject.h */
G_DECLARE_FINAL_TYPE (MyObject, my_object, MY, OBJECT, GObject)
這聲明瞭兩個結構體,MyObject 和 MyObjectClass。MyObject 必須在 C 實現中定義,而 MyObjectClass 已經由宏定義了。
由於 GObject 系統只是一個第三方庫,因此無法對 C 語言本身進行任何更改,建立新物件需要大量樣板程式碼。這主要由上面顯示的宏處理。但是,以下內容也是必需的
/* in myobject.h */
#define MY_TYPE_OBJECT my_object_get_type ()
該宏定義了幾個函式,即 MY_OBJECT() 和 MY_OBJECT_CLASS(),用於強制轉換,MY_IS_OBJECT() 和 MY_IS_OBJECT_CLASS() 用於測試物件或類是否為正確的型別,以及 MY_OBJECT_GET_CLASS() 用於從例項獲取類結構。
在使用之前,必須定義新建立的物件,以及例項結構體。
/* in myobject.c */
struct _MyObject
{
GObject parent_instance;
/* other members */
};
G_DEFINE_TYPE (MyObject, my_object, G_TYPE_OBJECT)
有一些靜態函式可能需要定義,也可能不需要定義,具體取決於您的物件。對於最小物件,這些函式是強制性的
/* in myobject.c */
static void
my_object_class_init (MyObjectClass *klass)
{
/* code */
}
static void
my_object_init (MyObject *self)
{
/* code */
}
在 C 中沒有內部方法可以分配記憶體給物件。因此,必須為新物件宣告一個顯式建構函式。
/* in myobject.c */
GObject *
my_object_new (void)
{
return g_object_new (MY_TYPE_OBJECT,
0);
}
雖然使用物件自己的指標型別來建立物件是完全有效的,但建議使用層次結構頂部的物件的指標型別,即最遠的基類。現在可以像這樣使用新建立的物件
/* in main.c */
/* Note: GObject is at the top of the hierarchy. */
/* declaration and construction */
GObject *myobj = my_object_new ();
/* destruction */
g_object_unref (myobj);
繼承是最廣泛使用和最有用的面向物件概念之一。它透過將現有程式碼包裝成一個物件,然後對其進行子類化,提供了一種有效的方法來重用現有程式碼。新的類被稱為派生類。可以使用繼承建立許多物件層次結構。繼承也是抽象程式碼的最有效方法之一。
在 GObject 系統中,可以透過對GObject進行子類化來實現繼承。由於 C 沒有提供繼承的關鍵字或運算子,因此派生物件通常是透過將基例項和基類分別宣告為派生例項和派生類的成員來建立的。在 C 程式碼中
/* derived object instance */
struct _DerivedObject
{
/* the base instance is a member of the derived instance */
BaseObject parent_instance;
};
- Hanser. "用 ANSI-C 進行面向物件程式設計". 1994. Hanser 描述了在標準 ANSI C 中實現類、繼承、例項、方法、物件、vtable、多型、後期繫結等的其他方法。
- Gregory Naçu - C64OS.com. "6502 中的面向物件(第二部分)". 2019. Greg Nacu 描述了在使用很少記憶體的6502 彙編語言中實現類、繼承、例項、方法、物件等的其他方法。
- Greg Kroah-Hartman. "關於 kobject、kset 和 ktype 的所有內容". 映象:"關於 kobject、kset 和 ktype 的所有內容". 2007.