0

次のコードに基づいて、Baseへのポインタを'Controller'クラスに格納するにはどうすればよいですか?

template< class Derived >
class Base
{
public:
  template < typename T >
  void Serialise( T* t )
  {
    Derived* d = static_cast< Derived* >( this );
    d->Serialise( t );
  }
};

class Derived : public Base< Derived >
{
public:
  template < typename T >
  void Serialise( T* t )
  {
    printf( "serialising to object T\n" );
  }
};

したがって、Serialise関数を呼び出してシリアル化するオブジェクトを渡すControllerクラスがある場合、必要なときにオブジェクトの型の一部であるため、派生型がわかっているポインターを格納する必要があります。実際の型が何であるかを知らずにBase型を使用します。

class Controller
{
public:
  void DoSerialise();

private:
  Base< Derived >* m_myObject; // I want this to just be Base* m_myObject but cant due to template!
};
4

3 に答える 3

1

簡単な答え-できません。

テンプレート引数がBaseのインターフェイスに影響を与えないと仮定すると(つまり、Derivedはどの関数シグネチャにも表示されません)、非テンプレートBaseクラスを使用でき、派生クラスはテンプレートである可能性があります。ただし、これは現在のパターンにはまったく適合しません。

あなたの場合、テンプレート引数がインターフェースに影響を与える場合(そしてこの場合は影響があると強く思う)、コントローラーはBaseを使用するためにDerivedについて知る必要があるので、Derivedについて知っていることの害はどこにありますか? Baseを宣言します。

コメント後に編集:派生クラスを任意のタイプにシリアル化できるようにしますか?Serialiser基本クラスから派生したクラスの階層を持たないのはなぜですか。そうすれば、Serialise()型への参照を受け入れてSerialiser、テンプレートパラメーターを失う可能性があります。

于 2013-02-12T12:54:45.830 に答える
0

あなたはそれをすることはできません。ただし、Base :: Serialiseが実行するのは、派生クラスのSerialiseメソッドを呼び出すことだけです。Baseがテンプレートパラメータを必要としないように、純粋に仮想化しないのはなぜですか?

于 2013-02-12T12:56:20.937 に答える
0

基本クラスの型は派生クラスの型に依存しているため、問題に対して実行したいと思われる特定のアプローチは不可能です。つまり、基本クラスのテンプレートのインスタンス化を単一の型として表現することはできません。これは、採用しているアプローチを実現するために必要です。

しかし、これは訪問者のパターンを物乞いする問題のようです。ビジター パターンにより、キャストせずにダブル ディスパッチが可能になります。考えられる解決策は次のとおりです。

// First declare a base serializable interface that accepts a serializer.

struct ISerializer;    

struct ISerializable {
  virtual void accept_serializer(ISerializer const &) const = 0;
};

// Now declare a base serializer type that can accept any serializable type.

struct Serializable1;
struct Serializable2;
...

struct ISerializer {
  virtual void serialize(Serializable1 const &) = 0;
  virtual void serialize(Serializable2 const &) = 0;
  ...
};

// Then implement your concrete serializable types to accept the serializer and
// invoke it on themselves.

struct Serializable1 : public ISerializable {
  void acceptSerializer(ISerializer const &s) const {
    s.serialize(*this);
  }
};

struct Serializable2 : public ISerializable {
  void acceptSerializer(ISerializer const &s) const {
    s.serialize(*this);
  }
};

// You can actually be a bit more clever to eliminate redundant code:

template<typename DerivedT>
struct SerializableAdapter {
  void acceptSerializer(ISerializer const &s) const {
    s.serialize(*static_cast<DerivedT const *>(this));
  }
};

struct Serializable1 : public SerializableAdapter<Serializable1> {
};

struct Serializable2 : public SerializableAdapter<Serializable2> {
};

// Finally, implement your concrete serializers, including one function for each
// serializable type.

struct Serializer1 : public ISerializer {
  void serialize(Serializable1 const &s) const {
    ...
  }

  void serialize(Serializable2 const &s) const {
    ...
  }
};

struct Serializer2 : public ISerializer {
  void serialize(Serializable1 const &s) const {
    ...
  }

  void serialize(Serializable2 const &s) const {
    ...
  }
};

// Now you can store the serializers through the base interface.

struct Controller {
  void doSerialize(ISerializable &p_serializable) {
    p_serializable.acceptSerializer(*m_serializer)
  }

private:
  ISerializer *m_serializer;
};
于 2013-02-15T23:41:20.070 に答える