0

汎用的に設計されたクラスがあり、どこでも使用できます。これは次のようになります。

class FixedByteStream {
public:
  FixedByteStream(const char* source)
  {
    size = strlen(source);
    copy(source);
  }

  /* Many more constructors here */

protected:
  void copy(const char* source)
  {
    address = allocate();
    //...
  }

  /* Plus other functions that call allocate() */

  char* FixedByteStream::allocate()
  {
    return (char*)malloc(size);
  }
}

次に、このクラスを拡張して、プロジェクト固有のメモリプールを使用できるようにしました。

class PooledByteStream : public FixedByteStream {
public:
  PooledByteStream::PooledByteStream() : FixedByteStream() {}

protected:
  char* PooledByteStream::allocate()
  {
    return (char*)PooledByteStream::pool.allocate(size);
  }
}

PooledByteStreamはFixedByteStreamと同じであると想定されていますが、allocate()が呼び出されたときにメモリプールからポインタを取得する必要があることを除いて、すべて同じ関数とコンストラクタがあります。

ただし、PooledByteStream :: alllocate()が呼び出されることはありませ。継承されたコンストラクターからでも、他の継承された関数(継承されたcopy()を呼び出す)からでもありません。基本クラスから継承されたものはすべて、allocate()が今ではまったく異なることを行うはずであるという事実に完全に気づいていません。

問題は、どうすればそれを修正できるかということです。継承された関数に、基本クラスの関数ではなく、オーバーライドされた関数を呼び出させるにはどうすればよいですか?基本クラスから必要なすべての関数をコピーして貼り付けると、継承のポイントが失われるため、ここではそれが答えではないと思います。

注:私は、メモリ管理や、同じ最終結果に到達するための他の方法についてのアドバイスを探していません。これはほんの一例です!

4

1 に答える 1

5

allocate()オーバーライドするには、仮想として宣言する必要があります。ただし、派生クラスがまだ構築されていないため、基本クラスコンストラクタは派生クラスのオーバーライドを呼び出すことができません。また、派生クラスはすでに破棄されているため、基本クラスデストラクタは派生クラスのオーバーライドを呼び出すことができません。

基本クラスのコンストラクターを呼び出す必要がある場合allocate()は、テンプレートを使用して制限を回避できます。例:

template<typename Derived>
class FixedByteStreamBase
{
public:
  FixedByteStreamBase(const char* source)
  {
    size = strlen(source);
    copy(source);
  }

  /* Many more constructors here */

protected:
  void copy(const char* source)
  {
    address = Derived::allocate();
    //...
  }

  /* Plus other functions that call allocate() */
};

class FixedByteStream : public FixedByteStreamBase<FixedByteStream>
{
public:
    static char* allocate()
    {
        return (char*)malloc(size);
    }
};

class PooledByteStream : public FixedByteStreamBase<PooledByteStream>
{
public:
    static char* allocate()
    {
        return (char*)pool.malloc(size);
    }
};

または:

struct MallocAllocator
{
    static char* allocate()
    {
        return (char*)malloc(size);
    }
};

struct PoolAllocator
{
    static char* allocate()
    {
        return (char*)pool.allocate(size);
    }
};

template<typename Allocator>
class FixedByteStreamBase {
public:
  FixedByteStreamBase(const char* source)
  {
    size = strlen(source);
    copy(source);
  }

  /* Many more constructors here */

protected:
  void copy(const char* source)
  {
    address = Allocator::allocate();
    //...
  }

  /* Plus other functions that call allocate() */
};

typedef FixedByteStreamBase<MallocAllocator> FixedByteStream;
typedef FixedByteStreamBase<PoolAllocator> PooledByteStream;
于 2013-01-12T04:20:06.157 に答える