5

私は特定の問題を抱えており、どちらのアプローチが他のアプローチよりも優れているかで立ち往生しています。

ユニオンメンバーのデータを定義する列挙型を持つ構造体または継承を持つクラスのグループ

サンプルコードを以下に示します。

ユニオンベースの構造

  typedef union TokenValue{
   bool bValue;
   long lvalue;
   double dvalue;
   std::string svalue;
   }

  class Token{
  public:
   TokenType type;
   TokenValue value;
   };

クラス継承

class TokenBase{
public:
  TokenType type;
  };



class TokenNumber: public TokenBase{
public:
bool isInt;
long lvalue;
double dvalue;
};

class TokenString: public TokenBase{
 public:
  std::string svalue;
 };
4

4 に答える 4

7

このタイプの設計は、識別された共用体またはタグ付き共用体として知られています。Googleで「C++の識別された共用体」を検索して、このタイプの設計のいくつかの例とアプローチを確認できます。

ACunionは通常、C ++にとっては少し低レベルで、安全ではないと見なされます。ピートベッカーが言ったように、あなたのベースのソリューションは、危険なメンバー unionを直接公開するのではなく、アクセサーを提供する必要があります。また、C ++ 11より前では、非PODデータ構造を含めることができないという欠点もあります(したがって、ありません)。unionunionstd::string

継承ベースのソリューションには、ポリモーフィズムの使用を開始できるという利点があります(たとえば、仮想PrintToメソッドを追加します)。(もちろん、オーバーを実行するPrintToメソッドをunionベースのソリューションに追加することで、同様の結果を達成できますが、それはOOではありません。)switchTokenType

ベースのunionソリューションは、おそらく継承ベースのソリューションよりも軽量です(no vtable)。これは、レクサートークンのような低レベルのものに適している場合があります。

サードパーティのライブラリが許可されている場合は、Boost.Variantを参照して、識別された共用体へのより多くのC++アプローチを確認することを強くお勧めします。

于 2012-08-23T15:16:27.877 に答える
4

クラスTokenは、「識別された共用体」と呼ばれるものを実装します。しかし、そのメンバーは公開されるべきではありません。これにより、タイプフラグを更新せずに、ユニオンに格納されているタイプを簡単に変更できます。代わりに、値を格納および読み取るためのオーバーロードされたアクセサーを提供します。値を格納するアクセサはbool、タイプフラグも設定する必要があります。他のアクセサーについても同様です。

于 2012-08-23T15:13:45.663 に答える
0

ほとんどの場合、継承はC++で推奨される方法です。ユニオンが好ましいと私が考えることができる唯一の状況は、データが同じビット数をとるが、それらのビットを解釈する適切な方法がまだわからない場合です。たとえば、signedまたはunsigned intのいずれかである可能性のあるソケットからビットの生のストリームを読み取っています。これは、後のコンテキストからわかります。それでも、通常、それを実装するためのよりクリーンな方法があります。

于 2012-08-23T15:15:52.750 に答える
0

いずれか/または:デフォルトでは、継承を優先する必要があります。組合はリスクが高く、誤用しやすい場合があります。この言語には、継承に関する優れた構文とセマンティクスがあります。

このユニオンの一般的な問題は、通常は自分から抽象化された実装の詳細(構築、破棄、モード、アクティブメンバーなど)を大量に定義する必要があることです。</ p>

コメントが示唆するように、より具体的な解決策については、問題を詳しく説明する必要があります。

于 2012-08-23T15:09:30.257 に答える