2011-11-06 8 views
5

疑問があります。以下の関数は、タイプAのオブジェクトまたは派生したタイプのオブジェクトを受け取ることができます。オブジェクトをヒープにコピーするためのnew演算子の使用

A *copyToHeap(A &obj) { 
    A *ptr=new A(obj); 
    return ptr; 
} 

我々はこのようにそれを呼び出す場合:

//B inherits from A 
B bObj; 
B *hPtr=copyToHeap(bObj); 

hPtrが指すオブジェクトが実際にタイプAまたはBのでしょうか? これは安全ですか?

答えて

4

あなたのコードで以下の操作を行うとき:

A* ptr = new A(obj); 

あなたは常にインスタンスを取得します。 objはAとして扱われ、新しいAはobjの "A part"に基づいて作成されます。

より良いアプローチは、以前の応答が示されているように、基本クラスに仮想MakeCopyメソッドを追加して、派生クラスのためにそれを実装しています。

virtual A* MakeCopy(); 

このメソッドは、呼び出されたオブジェクトのコピーを作成することによって実装されます。その後、派生クラスで実装されるようになります。したがって、実際にBオブジェクトであるAポインタがある場合は、真のBコピーを取得し、あなたの例で起こっている「スライシング」を避けます。あなたはA*hPtrの種類を変更する場合は、コンパイル

B *hPtr=copyToHeap(bObj); //error: invalid conversion from ‘A*’ to ‘B*’ 

を、しかし、あなたはまだ取得:

5

返されるオブジェクトのタイプはpointer to Aです。つまり、hPtrが指すオブジェクトのタイプはAです。 B以外のメソッドやメンバーを呼び出すと、クラッシュや未定義の動作が発生するため、安全ではありません。あなたはおそらくfactory patternを探しています。

1

それは間違っている、安全ではない、とコンパイラはあなたにいくつかの診断を与える必要があります。 GCCを使用している場合、g++ -Wallでコンパイルしようとしましたか?

+0

申し訳ありませんが、私はメモリからコードを書いて、私は喜んでしようとすることができませんでした。 – jlledom

2

安全な方法は

#include <memory> 

class Base 
{ 
public: 
    virtual std::unique_ptr<Base> Clone() = 0; 
}; 

class Derived : public Base 
{ 
public: 
    Derived(int i) : i_(i) 
    { 

    } 

    std::unique_ptr<Base> Clone() 
    { 
     return std::unique_ptr<Derived>(new Derived(i_)); 
    } 

private: 
    int i_; 
}; 


std::unique_ptr<Base> copyToHeap(std::unique_ptr<Base> obj) 
{ 
    return obj->Clone(); 
} 
1

がコンパイルされません仮想クローン方法を提供することですAオブジェクトです。あなたがAオブジェクトを作成し、Aで定義されたBオブジェクトのフィールドをコピーし、B一部をオフにスライスします使用Aのデフォルトのコピーコンストラクタ。このため、ポストに/上述のすべての問題の

0

- あなたはそれを避けることができます(と私はあなたができなかった理由を考えることはできません)すべての場合 - あなたが必要とするようにコードをデザインするべきではありません"copyToHeap"

Luchianが指摘するように、おそらく工場が必要です。ファクトリは、まずオブジェクトをヒープ上に作成します(そして、オブジェクト/ポインタ/メモリのライフタイムを管理するスマートポインタを返します)。

関連する問題