2

複数レベルの継承を持つクラス階層があります。

  1. cloneableを返す純粋仮想メンバー関数を宣言しますcloneable *
  2. baseから派生しますがcloneable、メンバー関数を宣言しません。
  3. 最後に、仮想関数derivedから派生しbaseて定義しますが、戻り値の型を にオーバーライドしますderived *

オブジェクトへのbaseポインタを介して仮想関数を呼び出すと、が返されます。に変換可能な仮想関数の実装が返されるため、私は期待していました。ここで何が起こっているのですか?derivedcloneable *base *derived *base *

で純粋仮想関数を宣言すればbase、ようやく取得できるのですがbase *、なぜこの宣言が必要なのかがわかりません。

コード:

struct cloneable
{
  virtual cloneable * clone() = 0;
};

struct base : cloneable 
{
// virtual base * clone() = 0;    // this line resolves the compile error
};

struct derived : base
{
  virtual derived * clone () { return new derived; }
};

int main(int, char**)
{
  derived d;
  base * bp = &d;
  base * bbp = bp->clone();  // error: invalid conversion 
                             // from ‘cloneable*’ to ‘base*’      
  return 0;  
}

注: コード例を短くするために、意図的に仮想デストラクタを省略しました。

4

1 に答える 1

4

base*コンパイラは、宣言なしで , を返すバージョンが必要だと正確にどのように推測する必要があると思いますか?


上記の質問はあなたの直接の質問に答えていますが、アドバイスを追加する必要があると思います.

初めに、

  • clone関数を作成して、オブジェクトまたは右辺値式を介してconst呼び出すことができるようにします。const

すなわち、

virtual cloneable* clone() const;

次に、オブジェクトのクローンを作成するには、

  • return new T( *this )(コピー コンストラクターを使用)、not new T(デフォルト コンストラクターを使用)。

そして第三に、

  • 安全のため、公開されている操作では、生のポインタではなく、cloneなどのスマート ポインタを返します。unique_ptr<MyClass>

ただし、戻り値の型がスマート ポインターに変更されたことで、C++ による共変関数 resultsのサポート (生のポインターと参照のみ) を直接利用できなくなります。そのための 1 つの方法は、public共変の結果の型を持つことができる生のポインターではない結果の実装と、単純にpublicスマート ポインターを返す型指定されたラッパーを使用することです。実際には、パブリック インターフェイスの共分散を自分自身で実装しているので、次のようになります。

#include <memory>       // std::unique_ptr
using namespace std;

class Base
{
private:
    virtual Base* virtualClone() const
    {
        return new Base( *this );
    }

public:
    unique_ptr< Base > clone() const
    {
        return unique_ptr< Base >( virtualClone() );
    }
};

class Derived
    : public Base
{
private:
    virtual Derived* virtualClone() const
    {
        return new Derived( *this );
    }

public:
    unique_ptr< Derived > clone() const
    {
        return unique_ptr< Derived >( virtualClone() );
    }
};

int main()
{
  Derived d;
  Base* bp = &d;
  unique_ptr< Base > bbp = bp->clone();
}
于 2012-09-17T04:01:04.463 に答える