2016-11-25 70 views
2

我需要解析XML並在C++中創建對應於XML元素的對象,並將XML元素的屬性作爲屬性打包到這些對象中。 XML元素/屬性和相應的C++類/屬性繼承自具有派生對象通用屬性的基礎對象。多態性或屬性字典?

我正在考慮使用基類的公共屬性和派生類只需要定義對象的特定屬性。然而,有人告訴我,使用標準多態不是一個好主意,因爲解決方案不夠通用 - 在XML中添加/更改屬性需要向C++類添加/更改相應的屬性,這需要更改太多的代碼。一個更好更抽象的解決方案是將一個屬性字典放在基類中,並通過搜索字典來訪問各個屬性。我想問社區這個建議是否對生產代碼更好。

下面是一個例子,其中車輛是基礎對象,並且不同的車輛類型從它繼承。 車輛物體具有所有車輛通用的nameweight屬性。下面是一個示例XML片段:

<car name="Toyota" weight="3500" passengers="4" /> 
<boat name="Yamaha" weight="3700" draft="16" /> 

基類:

class vehicle { 
    public: 
    string name; 
    string weight; 
}; 

派生類:

class car : public vehicle { 
    public: 
    string passengers; 
}; 

class boat : public vehicle { 
    public: 
    string draft; 
}; 

現在,當我的解析器發現汽車和船的元素我實例:

boat *b = new boat(); 
car *c = new car(); 

對於我可以簡單地訪問所有成員b->name,b->weightb->draft。在C++對象從XML實例化後,我們在每個屬性上完成了大量針對對象的工作,因此我們的目標不是簡單地將XML加載到程序中。

另一種方法:

#define TAG_XML_ATTRIBUTE_NAME    "name" 
#define TAG_XML_ATTRIBUTE_WEIGHT   "weight" 
#define TAG_XML_ATTRIBUTE_PASSENGERS  "passengers" 
#define TAG_XML_ATTRIBUTE_DRAFT    "draft" 
. . . 

class vehicle { 
    public: 
    map<string, string> arguments; 

    // Get argument by name searching the arguments dictionary. 
    string GetArgumentOrEmpty(const string& argumentName); 
}; 

class car : public vehicle { 
    public: // All propeties are in the base class dictionary. 
}; 

class boat : public vehicle { 
    public: // All propeties are in the base class dictionary. 
}; 

所有派生類具有arguments圖;爲了得到屬性值,我們掃描詞典以按名稱查找屬性,然後讀取它的值,例如, GetArgumentOrEmpty(TAG_XML_ATTRIBUTE_WEIGHT)。現在的CPU速度很快,因此搜索字典不會明顯影響性能。元素/屬性的命名空間從結構化(作爲類成員)到平坦(作爲#define列表),但它們將全部位於同一位置。代碼更抽象;儘管對象處理代碼由於額外的間接尋址而變得更加複雜,但如果屬性名稱更改,則不需要更改;例如如果在XML改變peoplepassengers,#定義會顯得有點尷尬,但使用它不會有更改代碼:

#define TAG_XML_ATTRIBUTE_PASSENGERS  "people" 

是否基於字典的屬性訪問方法存在足夠的好處將其用於生產代碼而不是使用常規的類屬性?如果是這樣,是僅僅爲了這個特定的XML解析情況還是用字典搜索替換多態性並用字符串名稱替換類屬性通常是一個更好的主意?

回答

1

的基於字典的方法確實有幾個優點:

  • 可以很容易地新新屬性添加到一個類/對象。
  • 對象加載/保存/創建代碼將是非常通用的。
  • 這有可能使屬於類完全可配置的屬性
  • 事實上,一些遊戲編碼專家,如Mike McShaffry(「Game Coding Complete」)主張用這樣一種‘組件’架構爲代表的遊戲角色,而不是深層次的繼承層次,這些層次更難維護和豐富。

有一對夫婦的不便,以及:

  • 類特殊處理代碼將與干將
  • 被堆滿此代碼將在很大程度上取決於物業的命名,這使得可配置不太容易。
  • 由於未被注意到的拼寫錯誤,很容易將錯誤導入系統:編譯器不會發現這些不一致,因爲它只是臨時數據。

所以你必須做出艱難的選擇。我的建議是:

  • 如果您有複雜的類相關處理代碼,那麼它會很容易出錯,堅持您的原始方法。知道你正在使用的成員變量的編譯器的好處是可靠性的保證。
  • 如果您只有幾個與類相關的例程,並且屬性大多是描述性的並以類似的方式處理,那麼如果您需要易於擴展和可配置的對象結構,則採用地圖方法
  • 是有意義的,第二種方法也是更靈活的方法。

如果你去的地圖,一對夫婦的想法:

  • 你能想到的外部屬性的名稱和內部整數相當於代表它之間的字典。這將避免大量的字符串處理開銷,從而加速地圖。
  • 你可以設想使用unordered_map來避免太多的字符串比較。
+0

Christophe,你能否請你完成你的想法「事實上,一些遊戲編碼專家,比如......」 - 這裏的細節非常有價值。 – sun2sirius

+0

@ sun2sirius對不起,在寫作過程中,這句話被切斷了,並失去了。我編輯完成了這個句子。 – Christophe