2016-11-25 6 views
2

私はXMLを解析し、XML要素に対応するC++でオブジェクトを作成し、XML要素の属性をプロパティとしてそれらのオブジェクトにパックする必要があります。 XML要素/属性および対応するC++クラス/プロパティは、派生オブジェクトと共通のプロパティを持つ基本オブジェクトから継承します。多型またはプロパティの辞書?

私は共通のプロパティに基本クラスを使用することを考えていました。派生クラスはオブジェクト固有のプロパティを定義するだけで済みます。しかし、誰かが、標準的な多型を使用するのは良い解決策ではないと言いました。なぜなら、XMLの属性を追加/変更するには、対応するプロパティをC++クラスに追加/変更する必要があります。 。はるかに良く、より抽象的な解決策は、基本クラスに属性の辞書を置き、辞書を検索することによって個々のプロパティにアクセスすることです。私はこの提案がプロダクションコードの方が良いかどうかコミュニティに尋ねたいと思っていました。

以下は例です。車両がベースオブジェクトであり、異なる車種がそれを継承しています。 車両オブジェクトには、すべての車両に共通のプロパティnameweightがあります。

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

基本クラス:

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

派生クラス:ここでは、サンプルのXMLフラグメントである

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

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

が今私のパーサは、車やボートの要素を見つけたとき、私はインスタンス化:

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

ボートb->nameb->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リスト)になりますが、それらはすべて1か所にあります。コードはより抽象的です。追加の間接化によりオブジェクト処理コードはより複雑になりますが、属性名が変更されても変更する必要はありません。例えばpeopleにXMLの変更でpassengers場合、の#defineは少し厄介になりますが、それは変更する必要はありません使用するコード:

#define TAG_XML_ATTRIBUTE_PASSENGERS  "people" 

辞書ベースのプロパティへのアクセス方法は、十分に利益を提示してい通常のクラスプロパティを使用する代わりにプロダクションコードに使用しますか?もしそうなら、この特定のXML解析のケースのみであるか、多型を辞書検索で置き換え、クラスプロパティを文字列名で置き換えるのが一般的には良いアイデアですか?

答えて

1

辞書ベースのアプローチは確かに利点のカップルを持っている:

  • それはクラス/オブジェクトに新しい新しいプロパティを追加するのは簡単です。
  • オブジェクトの読み込み/保存/作成コードは非常に一般的です。
  • それはゲームの俳優を表現するための 『コンポーネント』アーキテクチャのような種類の使用を提唱(「Game Coding Complete」)実際には、いくつかのゲームは、Mike McShaffryなどの専門家をコーディング
  • クラスに所属する性質が完全に設定することが可能ですが、より深く継承された階層ではなく、維持したり豊かにすることができます。

    • クラス固有の処理コードがゲッター
    • で雑然とされるだろう。このコードは、コンフィギュラが少なく容易になり、プロパティの命名、に大きく依存します:

    は、同様の不具合がいくつかあります。

  • 誤ったタイプミスのためにシステムにバグをつけるのは簡単でしょう。コンパイラは、このような不一致をスポットしないでしょう。

あなたは難しい選択をする必要があります。私の助言は:

  • 複雑なクラスに依存する処理コードをお持ちの場合は、エラーが発生しやすく、元の方法に固執します。使用しているメンバ変数を知っているコンパイラの利点は、信頼性の保証になります。
  • クラス依存ルーチンが2つしかなく、プロパティがほぼ記述的で同様の方法で処理されている場合は、簡単に拡張可能で構成可能なオブジェクト構造が必要な場合は、マップアプローチをとることが便利です。
  • 第2のアプローチは、より柔軟なアプローチでもあります。

あなたがマップ、思考のカップルのために行く場合:

  • あなたは外部のプロパティ名と、それを表現するための内部整数相当の間辞書考えることができます。これは、多くの文字列処理のオーバーヘッドを避けることによってマップを高速化します。
  • は、あまりにも多くの文字列比較を避けるためにunordered_mapを使用することができます。
+0

Christophe、 "実際にはいくつかのゲームコーディングのエキスパートの周りであなたの考えを終わらせてください..." - 詳細はここで非常に貴重です。 – sun2sirius

+0

@ sun2sirius申し訳ありませんが、文章は途中で途切れて失われました。私は文章を完成させるために編集しました。 – Christophe

関連する問題