2009-04-13 79 views
2

我一直在閱讀一些關於元類的內容,但我想知道它們是否可以在C++中實現。如何在C++中實現元類?

我知道Qt庫正在使用MetaObjects,但它使用C++的擴展來實現它。我想知道它是否可以直接在C++中使用。

謝謝。

回答

1

可以創建元類,但是C++並不是這樣的,它是關於基於靜態編譯時的實現,而不是運行時的靈活性。

無論如何,這取決於你是否想要方法的Meta-Classes,或者只需要Meta-Classes與數據,Data類可以用Boost構造如boost :: any來實現,如果你想要方法的類,可以使用boost :: bind方法綁定到對象,或者你可以用COM-objects之類的單入口點接口自己實現它們。

然而,「真正的」C++方法是使用泛型,因此它可以在編譯時確定,以獲得最佳性能。老實說,雖然我見過很少的系統,但真正需要運行時的靈活性,在大多數情況下,對象是天生的,死於同一個類,或者至少足夠花95%的系統一旦他們從工廠出來,他們終身成爲一個班級。

所以在許多情況下,人們會發現自己爲運行時元類付出太多。當然,有一種觀點認爲,這可以提供更好的開發人員性能,但在許多情況下,每行代碼將在硬件上運行,比寫它的時間多幾億倍。因此,您可以將編譯時和運行時類考慮爲付費或永久租用。我個人喜歡先付款。

3

Gamma等人在書籍「設計模式」中的幾種模式與元類概念具有相似的特徵。例如,「策略」模式允許您在創建時自定義對象行爲。信封成語是另一個密切的匹配。儘管如此,也不要讓你自定義該類的接口。

在COM中,IDispatch接口允許在運行時向對象動態添加方法/屬性。這意味着放棄標準的C++方法調用。每次調用都會經歷相同的方法,該方法將索引或字符串鍵引入用戶維護的方法/屬性表中,並且所有參數都必須作爲對象數組傳遞。

使用這兩種技術可以獲得元類的靈活性,但是由於沒有語法優勢或運行時/編譯器的幫助,這是一個更難的方法。

戴夫

1

不怕......至少不是天生的。

擁有一個元類通常需要有一個表示類的運行時對象,就像Java中的情況一樣。

在C++中,類沒有運行時表示。它們的表現發生在虛擬表格之類的事物中。但是在很多方面,它們都像C函數一樣操作,所有的OOP幾乎都以膠水代碼的形式運行。

這就是說,有很多事情你可能想要用其他語言的元類來實現OOP模式。你也可以「模擬」你自己的對象系統。

3

如果元類的工作定義爲「一個語言實體,其實例是自己班」,然後仿製藥在C元類++:

#include <iostream> 
using namespace std; 

template <typename T> 
class Meta { 
public: 
    Meta(const T&init) : mData(init) {} 
// ... 
private: 
    T mData; 

}; 

int main(int, char **) { 
    cout << "The size of Meta<double> is " << sizeof(Meta<double>) << endl ; 
    return 0; 
} 

在倒數第三行中的雙>使用元<的強迫編譯器實例化Meta <雙>類; sizeof操作符在Meta上運行,從而證明這不是簡單的語義糖,並且類已經被實例化。即使沒有實例化Meta類型的對象,程序也是完整的。

3

C++沒有內置的對元類的支持(不是以Python/Objective-C方式),但是你可以手動模仿元類的行爲。基礎非常簡單,您可以創建一個具有較長使用壽命的額外類(單例,靜態對象或Construct On First Use Idiom),該類可以創建和操作相應的類。 (在Objective-C中,元類通常包含'靜態'成員變量,內存分配/釋放例程等等)。

Qt做了什麼,他們採用了元類的概念並對其進行了修改,以便它們可以支持某種形式的Reflection(以及不支持它的系統上的RTTI)。實現這將需要大量的宏魔法或自定義編譯器(比如他們已經選擇使用)。

通常,C++語言已經提供了大部分常規元類提供的功能,只是以不同的形式。實際上,想要元對象的唯一原因是出於反射的目的,如this document中概述的那樣,在C++中實現反射有不同的方法。除此之外,如果你真的設置了一個Objective-C風格的元類系統,我不知道有任何庫可以這樣做,但很可能。另一方面,滾動你自己也不應該那麼困難。