0

以下のクラス HandleMessages には、タイプ ProtocolDecoder* のメンバー変数があります。ProtocolDecoder がテンプレート クラスではない場合、これは問題ありませんでした。今はそのように変更しましたが、コードはコンパイルされません。

実行時に、必要なデコーダーを作成するファクトリー関数があります。

メンバー m_Decoder を持てない場合、どうすれば同じ効果を達成できますか?

メンバーを ProtocolDecoder* m_Decoder; として宣言しようとすると、

コンパイラ エラーが発生します: エラー C2059: 構文エラー: '<'

コンパイルされているクラス テンプレートのインスタンス化 'LogPlayer' への参照を参照してください。

template <typename T>
class ProtocolDecoder 
{
public:
  virtual const char* ProtocolName() = 0;
  virtual ProtoWrapper<T>* DecodeMsg(const unsigned char* msg, int length) = 0;
 ...
};

class ABCDecoder : public ProtocolDecoder<ABC_msg>
{
public:
  virtual const char* ProtocolName() {return "ABC"; }

  virtual ProtoWrapper<ABC_msg>* DecodeMsg(const unsigned char* msg, int length);
};

//lots of different decoders derived from ProtocolHandler

class HandleMessages 
{
public:
void Process() {}

private:
//ProtocolDecoder<T>*      m_Decoder;  //Want a Protocol member variable - but don't know type until runtime
};
4

4 に答える 4

1

テンプレート パラメータを指定せずにテンプレート オブジェクトを使用することはできません。テンプレート タイプは、すべてのパラメータに値がある場合にのみ存在します。

そのため、 whileProtocolDecoder<int>*は実数型ですが、そうでProtocolDecoder<T>*はありません。おそらくここで必要なのは、すべてのテンプレート クラスの派生元となる抽象基本クラスを作成することです。次に、それらを基本型に単純にアップキャストして、そのように保存できます。

たとえば、

class BaseProtocolDecoder 
{
public:
  virtual const char* ProtocolName() = 0;
  virtual BaseProtoWrapper* DecodeMsg(const unsigned char* msg, int length) = 0;
 ...
};

template <typename T>
class ProtocolDecoder : BaseProtocolDecoder
{
public:
  const char* ProtocolName();
  BaseProtoWrapper* DecodeMsg(const unsigned char* msg, int length);
 ...
};

template<>
ProtocolDecoder<ABC_msg>
{
public:
  const char* ProtocolName() {return "ABC"; }

  BaseProtoWrapper* DecodeMsg(const unsigned char* msg, int length);
};

ProtoWrapper<T>同じ理由で、 に対しても同じことを行う必要があります

注: 多くの場合、テンプレートは厳密には必要ないため、テンプレートを捨てて単純に継承を使用したいと思うでしょう。もちろん状況にもよりますが、テンプレート化されたコードをときどき見直して、「テンプレートを取り出せないだろうか」と考えるのは常に良いことです。

于 2012-11-12T17:49:06.153 に答える
0
class BaseWrapper
{
};

template <class T>
class ProtoWrapper: public BaseWrapper
{
};

class BaseDecoder
{
  virtual const char* ProtocolName() = 0;
  virtual BaseWrapper* DecodeMsg(const unsigned char* msg, int length) = 0;
};

template <typename T>
class ProtocolDecoder: public BaseDecoder
{
public:
 ... // template specific code
};

class ABCDecoder : public ProtocolDecoder<ABC_msg>
{
public:
  virtual const char* ProtocolName() {return "ABC"; }

  virtual ProtoWrapper<ABC_msg>* DecodeMsg(const unsigned char* msg, int length);
};

class HandleMessages 
{
public:
void Process() {}

private:
BaseDecoder*      m_Decoder;  //Want a Protocol member variable - but don't know type until runtime
};
于 2012-11-12T17:57:03.373 に答える
0

言われた他のことを少し追加するには:ここであなたの決定を下すべき主な問題は、実行時にそのような選択をするためにポリモーフィズムなどを必要とする一方で、テンプレートはコンパイル時に決定されるということだと思います。

于 2012-11-12T18:08:23.487 に答える
0

ProtocolDecoder の完全なテンプレートを見ないと、これがアプリケーションで機能するかどうかはわかりませんが、インターフェイスを独自のクラスにプルします。次に、HandleMessages() クラスにはインターフェイスへのポインター/参照があり、テンプレートは気にしません。

実装ではなくインターフェイスへのプログラム: 「インターフェイスへのプログラム」とはどういう意味ですか?

于 2012-11-12T17:56:33.933 に答える