2009-08-28 119 views
2

我想一個虛擬類是這樣的:虛擬數據類型/枚舉

class Configuration 
{ 
public: 
    enum EPromptId; 

    virtual CString getPrompt(EPromptId promptId) = 0; 
private: 
}; 

讓每個派生的配置都可以有它自己的一套EPromptIds

class Configuration1 : public Configuration 
{ 
public: 
    enum EPromptId{ 
     epid_HappyBirthday 
    }; 

    CString getPrompt(EPromptId promptId){ 
     return ""; 
    } 
private: 
}; 

class Configuration2 : public Configuration 
{ 
public: 
    enum EPromptId{ 
     epid_JummpingJehoshaphat 
    }; 

    CString getPrompt(EPromptId promptId){ 
     return ""; 
    } 
private: 
}; 

因爲每個類都需要implment這種失敗的一個具有Configuration :: EPromptId參數的虛擬函數(不是此代碼中的Configuration1 :: EPromptId或Configuration2 :: EPromptId)。

是否有可能讓基類識別參數類型,但在每個派生類中定義不同的值(可能不使用枚舉,但保留強類型,即不使用int)。

編輯:我想兩個不同的'應用程序'的兩個不同的配置。提示可以保存在數據庫表中,但每個「應用程序」都有它自己的表格。一個指向基本配置類的指針被包含在一個與某些硬件接口的類中(即進行實際顯示)。硬件是一種可用於請求和接收用戶輸入的io設備。當創建硬件類時,它將傳遞一個指向正確配置類的指針,並在請求時顯示正確的提示。

+0

這是否必須是一個'enum'? 'const int'也可以嗎? – sbi 2009-09-01 17:55:18

+0

需要成爲一個枚舉。 – Patrick 2009-09-02 11:32:02

回答

3

第一步:你想要一個摘要類。 (抽象類是具有至少一個純虛函數一個虛基類是一個類,是來源於virtual。)

然後:不,你想要什麼是不可能的。您不能轉發 - 宣佈enum並在稍後定義它,更不用說對其進行不同的定義。即使你可以:如果有人通過epid_HappyBirthdayConfiguration2哪些不知道它會發生什麼?

,我建議你向我們解釋你想要做的(而不是你以爲你找到如何做到這一點的方式是否有效),也許有人能拿出一個成語來解決你的問題是什麼

+0

請參閱編輯 – Patrick 2009-08-28 11:37:52

+0

將epid_HappyBirthday傳遞給Configuration2將是一個錯誤,很簡單。 – Patrick 2009-08-28 11:41:02

1

您不能混合編譯時類型檢查和運行時虛擬函數解析。

你可以有通用

class Configuration 
{ 
public: 
    virtual CString getPrompt(int promptId) = 0; 
private: 
}; 

和衍生品定義兩個成員函數:

class Configuration1 : public Configuration 
{ 
public: 
    enum EPromptId{ 
     epid_HappyBirthday 
    }; 

    CString getConfiguration1Prompt(EPromptId promptId){ 
     return ""; 
    } 
    virtual CString getPrompt(int promptId) 
    { 
     return getConfiguration1Prompt(static_cast<EPromptId>(promptId)); 
    } 
private: 
}; 

class Configuration2 : public Configuration 
{ 
public: 
    enum EPromptId{ 
     epid_JummpingJehoshaphat 
    }; 

    CString getConfiguration2Prompt(EPromptId promptId){ 
     return ""; 
    } 
    virtual CString getPrompt(int promptId) 
    { 
     return getConfiguration2Prompt(static_cast<EPromptId>(promptId)); 
    } 
private: 
}; 

如果你想確保有效promptId應手動檢查它在運行時的子類。

無論如何,這種方法沒有用,因爲要使用通用的getPrompt()函數,您需要知道您使用哪個子類來訪問其EPromptId

+0

請注意,在此示例中,epid_HappyBirthday和epid_JummpingJehoshaphat可能具有相同的值(0)。您應該在基類中創建一個單獨的枚舉,該枚舉包含派生類中使用的所有枚舉值。這不是很面向對象,但它是我知道解決這些問題的唯一方法。 – 2009-08-28 11:22:06

+0

getPrompt是純虛擬的,所以你將永遠知道在運行時調用哪個子類 – Patrick 2009-08-28 11:22:14

+0

@ StefanWoe,它們肯定會有相同的值,這就是我想要的 – Patrick 2009-08-28 11:23:05

0

我的C++是有點生疏,但如果你想手動控制每個ID,只需添加一個和int構造你不能這樣做

struct EPromptId { 
    EPromptId() mId(sId++) { } 
    operator int() { return mId; } 
    friend static bool operator==(EPromptId lhs, EPromptId rhs) { 
     return lhs.mId == rhs.mId; 
    } 
private: 
    int mId; 
    static int sId; 
}; 

struct configuration1 { 
    static const EPromptId epid_HappyBirthday; 
    static const EPromptId epid_xxx; 

    CString getPrompt(EPromptId promptId){ 
     if (promptId == epid_HappyBirthday) 
      return ""; 
     else if (promptId == epid_xxx) 
    } 
} 

// somewhere else 
EPromptId configuration1::epid_HappyBirthday; 
EPromptId configuration1::epid_xxx; 


EPromptId(INT ID)MID(ID ){}

,改變初始化

EPromptId configuration1::epid_HappyBirthday = 1; 
EPromptId configuration1::epid_xxx = 5; 
+0

我不認爲,這有什麼用處。對於所有派生類,該靜態變量只存在一次 - 並且每次調用構造函數時它都會增加。 – 2009-08-28 15:43:41

+0

糟糕,錯過了初始化並添加了手動編號 – adrianm 2009-08-28 16:12:21

3

你也許能夠得到你最想要什麼用的模板......作爲LON g,因爲你不希望保留在Configuration*的集合中,並以這種方式訪問​​它們(你不是,是嗎?因爲你需要知道它們的類型知道該怎麼過呢....)

template< typename ENUM_TYPE > 
class Configuration 
{ 
public: 
    virtual CString getPrompt(ENUM_TYPE promptId) = 0; 
private: 
}; 

然後

enum EPromptId{ 
    epid_HappyBirthday 
}; 

class Configuration1 : public Configuration<EPromptId> 
{ 
public: 
    CString getPrompt(EPromptId promptId){ 
     return ""; 
    } 
private: 
};