2010-04-17 223 views
2

我有一個從框架中的基類派生的C++類。繼承 - 初始化問題

派生類沒有任何數據成員,因爲我需要它可以自由轉換爲基類並返回 - 框架負責加載和保存對象,我無法更改它。我的派生類只具有訪問數據的功能。

但是有幾個地方我需要存儲一些臨時的局部變量來加速訪問基類中的數據。

mydata* MyClass::getData() { 
    if (!m_mydata) { // set to NULL in the constructor 
     m_mydata = some_long_and complex_operation_to_get_the_data_in_the_base() 
    } 
    return m_mydata; 
} 

的問題是,如果我只是通過從鑄造框架返回MYCLASS *爲MyClass的構造函數將永遠不會調用和m_mydata是垃圾的基類指針訪問對象。
有沒有辦法只初始化m_mydata指針一次?

+0

雖然這不是更糟嗎?如果您將基類指針強制轉換爲「MyClass *」,那麼如何知道分配的內存中是否有足夠的空間用於新的'm_mydata'成員?除非你分配內存,然後框架填充它 - 在這種情況下,你可以構造你的'MyClass'並將指向基類的指針傳遞給框架。 – 2010-04-17 20:50:18

回答

1

它沒有成員,您必須保持按位存儲器佈局的兼容性...除了它和C++沒有可自由兌換的概念。

如果現有的框架分配基礎對象,那麼您實際上無法從中派生出它。在這種情況下,我能想到的兩個選項:

  • 定義自己的類Cached引用其鏈接到Base。將參考公開和/或複製Base的接口而不繼承。
  • 使用散列表,unordered_map< Base *, mydata > mydata_cache;。這對我來說似乎最合適。在委託給Base *之前,請使用免費函數查找緩存數據。
+0

謝謝 - 看起來這只是在C++中做的一件愚蠢的事情 – user280760 2010-04-22 22:57:17

1

你可以初始化私有變量在一個單獨的初始化成員函數,所以是這樣的:

class MyClass { 
    public: 
    init() { 
     if (!m_mydata) { 
     m_mydata = f(); 
     } 
    } 
}; 

framework_class_t *fclass = framework.classfactory.makeclass(); 
MyClass *myclass = (MyClass*)fclass; 
myclass->init(); 
char *mydata = myclass->getData(); 

這很難說,如果這是一個好主意或沒有不知道你用什麼框架,或看到你的代碼。這是閱讀你的描述後想到的第一件事。

+0

這就是我正在做的 - 但很容易錯過一個。我想知道是否有一些'魔術'C++初始化技巧,我不知道自動執行此操作。 – user280760 2010-04-17 20:37:21

+0

如果您有權訪問框架類定義,那麼您可以重載轉換運算符,但那對於框架來說不是很好的風格(有多少派生類型必須支持轉換?)。 如果你不喜歡manual + :: init()方法,那麼也許你可以使用宏或其他函數,這樣你就不會忘記調用:: init()。 – 2010-04-19 03:07:18

1

您可以爲框架的工廠創建包裝。包裝將具有相同的接口,委託調用框架,但它可以在返回之前初始化創建的基類實例。當然,這需要你改變你的代碼來使用包裝器,但如果可能的話,那麼你可以確保初始化正確發生。

對此的一種變化:通過將基類實例包裝到可以在其構造函數中進行初始化的自定義自動檢查程序來使用RAiI。同樣,如果你設法改變代碼來直接使用新的包裝類型而不是派生類,那麼你是安全的。