2010-04-23 130 views
0

我有一個C++項目QT開發。我正在運行的問題是我想要一個基類,我的所有屬性類都繼承,以便我可以將它們全部存儲在一起。現在,我有:C++財產類結構

class AbstractProperty 
     { 
     public: 
      AbstractProperty(QString propertyName); 
      virtual QString toString() const = 0; 
      virtual QString getName() = 0; 
      virtual void fromString(QString str) = 0; 
      virtual int toInteger() = 0; 
      virtual bool operator==(const AbstractProperty &rightHand) = 0; 
      virtual bool operator!=(const AbstractProperty &rightHand) = 0; 
      virtual bool operator<(const AbstractProperty &rightHand) = 0; 
      virtual bool operator>(const AbstractProperty &rightHand) = 0; 
      virtual bool operator>=(const AbstractProperty &rightHand) = 0; 
      virtual bool operator<=(const AbstractProperty &rightHand) = 0; 
     protected: 
      QString name; 
     }; 

然後我採取類如PropertyFloat和PropertyString和基於這樣的假設比較運營商,只有字符串被用繩子等相比,提供的實現。但是這個問題是不會有什麼錯誤編譯時拋出,如果我做了

if(propertyfloat a < propertystring b) 

但是我實現運營商的每一個派生類依賴於他們兩個是相同的派生類。所以我的問題是我不知道如何實現一個屬性結構,以便我可以讓它們都從一些基本類型繼承,但代碼就像我上面會引發編譯時錯誤。

如何可以做到這一點任何想法?對於那些熟悉QT我也試過用用的QVariant一個實施然而的QVariant沒有運營商<和>只有在一些派生類的本身定義,因此它沒有工作了。

什麼我的最終目標是,是能夠泛指性。我有一個元素類,其中包含一個字符串'name'作爲鍵和AbstractProperty作爲值的屬性的散列圖。我希望能夠在屬性上進行一般操作。即如果我想獲得給定字符串名稱的屬性的最大值和最小值,我擁有完全通用的方法,將從每個元素中提取相關的AbstactProperty,並查找最大/最小值,而不管類型是什麼。所以屬性雖然最初聲明爲PropertyFloat/PropertyString,但它們將一般保持不變。

+1

你在做什麼你的財產類?你從中得到什麼好處? – 2010-04-23 18:45:26

回答

1

另一種解決方案是使用Curiously Recurring Template Pattern。這允許模板化類根據派生類定義比較運算符。

例子:

template <class Descendant> 
struct Numeric_Field 
{ 
    Descendant m_value; 

    bool operator==(const Descendant& d) 
    { 
     return m_value == d.value; 
    } 
    bool operator!=(const Descendant& d) 
    { 
     return !(*this == d); 
    } 
    bool operator< (const Descendant& d) 
    { 
     return m_value < d.m_value; 
    } 
    bool operator<=(const Descendant& d) 
    { 
     return (*this < d) || (*this == d); 
    } 
    bool operator> (const Descendant& d) 
    { 
     return !(*this <= d); 
    } 
    bool operator>=(const Descendant& d) 
    { 
     return !(*this < d); 
    } 

protected: 
    Numeric_Field(const Descendant& new_value = 0) 
    : m_value(new_value) 
    { ;} 
}; 

這可能是做了個比較通用的通過使用純虛保護getter和setter方法代替m_value

template <class Descendant_Type> 
struct Numeric_Field_2 
{ 
    virtual const Descendant_Type get_value(void) const = 0; 
    virtual void      set_value(const Descendant& new_value) = 0; 

    bool operator==(const Descendant_Type& dt) 
    { 
     return get_value() == dt.get_value(); 
    } 
    bool operator< (const Descendant_Type& dt) 
    { 
     return get_value() < dt.get_value(); 
    } 
}; 

在這一點上,你可以繞過在需要比較的地方,指向Numeric_Field。我相信這只是一個打字保護程序。

5

如果有什麼,而不是使之類的比較運營商會員,你讓他們的全球職能?

如果你這樣做,那麼你可以爲每個給定類型和控制操作,其類型可以互相比較:

bool operator==(const PropertyFloat &leftHand, const PropertyFloat &rightHand); 
bool operator==(const PropertyString &leftHand, const PropertyString &rightHand); 

編譯器會抱怨任何時候,你這樣做:

if(propertyfloat a == propertystring b) 
現在

,爲了獲得必要的私有數據的比較,使派生類的這些全局函數的「朋友」。

+0

+1用於提示全局功能。全局函數也可以使用模板進行概括。 – 2010-04-23 20:51:09

+0

這是一個很好的方法,我可能最終不得不走這條路,但我的主要猶豫是,那麼我不能再將所有的信息放在元素類中。或者,如果我把它作爲一般的基類,那麼我必須有一些大的swtich鑄造語句才能達到正確的等級,以便讓操作員失去意識。 – 2010-04-26 15:51:40

+0

也許你應該檢討你的設計。平等和排序比較只應在特定(葉)類上執行。 – 2010-04-26 16:25:21

2

我在設計中的一個也有類似的問題,直到我沉思了它。我意識到在基類中有比較運算符是錯誤的。正如你所發現的,基類中的比較方法是比較任何後代類的組合。這是糟糕的噶瑪。

更好的辦法是在子孫類定義比較運算符。這將幫助編譯器防止使用不同類型的操作員的人員。這樣做的副作用是一個不能由解引用指針的基類(這將是一件好事)比較對象。

另一個有用的工具是加速比較模板。尋找equality_comparable

+0

如果我最終沒有在基類中聲明的比較,並且我經常不得不投入後代類。這意味着當我想進行比較以確定要拋棄的類型時,需要使用大型開關/案例語句。你是如何看待這個的?我真的想保持我的元素類只有一個屬性的hasmap,所以我們可以擁有任何類型的屬性,但這需要將其一般存儲爲基礎。 – 2010-04-26 15:50:25

+0

我絕對需要時只傳遞基類指針。很少有我不得不沮喪的情況。此外,我所擁有的唯一「開關/外殼」聲明在工廠。我嘗試將通用代碼傳播到基類或父類中。我有通用的'Field'和'Record'類,使數據庫接口更簡單。我有特定的'Recipe','Ingredient'和'Menu'類。爲了使用數據庫,'Ingredient'從Record繼承,所以數據庫將它視爲一條記錄,而不需要知道具體細節。 – 2010-04-26 16:23:31