2017-07-29 17 views
0

を削除するには、私持って次のセットアップ:コールは、暗黙的にコピーコンストラクタ

class MyClass { 
public: 
    static MyClass Clone(const MyClass& other) { 
    return MyClass(other, 10); 
    } 

    static MyClass CreateNormal(int x, int y) { 
    return MyClass(int x, int y); 
    } 

    // There are a few more factory functions. 

private: 
    // Constructor 1 
    MyClass(int x, int y) : b_(x, y) {} 

    // Constructor 2 
    MyClass(const MyClass& other, int c) : b_(other.b_, c) {} 

    // And a lot more constructors. 


    // NotMyClass has its copy constructor deleted. 
    NotMyClass b_; 
} 

int main() { 
    MyClass A(1,2); 

    MyClass B = MyClass::Clone(A); // ERROR 
} 

NotMyClassを変更することなく、これを回避する方法はありますか? コピーコンストラクタMyClassが暗黙的に削除されたため、エラーが発生します。これを解決するために私はstd :: Move()を使う方法がありますか?

実際のクラスには多くのコンストラクタがあり、わかりやすくするためにファクトリ関数が必要なため、ファクトリ関数を削除することはできません。

+0

どのC++標準が利用可能ですか? – HeroicKatora

+0

NotMyClassに移動コンストラクタがありますか? – tweej

+1

コピーできないオブジェクトを複製したい場合は、 'NotMyClass'自体に' clone() 'メソッドがあることを願ってください。さもなければあなたはそのデザインを打破しようとしています。このコピー不可能なものをコピーしてもよろしいですか?あなたはそれへの参照を保持したくないですか? –

答えて

1

C++ 11標準の利用可能性を仮定すると、あなたが代わりにそうように、新しいオブジェクトを構築するファクトリメソッドによって返された右辺値参照の寿命を延ばすことができます:

MyClass A(1, 2); 
MyClass&& B = MyClass::Clone(A); 

補遺: として、以下のコメントでpatatahooliganが指摘したように、ご自分のバージョンMyClass::Cloneにコピーコンストラクタの呼び出しがある可能性があります。これは、/ C++ 17は必須コピーエリジオンが付属していたら、このすべてが完全に、不要ななります

MyClass MyClass::Clone(const MyClass& other) { 
    return {other, 10}; 
} 

に書き換える必要があることができ、あなたがそれを楽しみにすることができますので、来ます。


C++ 03では、ソリューションがより長く、より多くのコードを必要とするにもかかわらず、望ましい結果を達成することは可能です。

静的メソッドのセットを作成する代わりに、tag-dispatchを使用して異なるコンストラクタの意味を知らせることをお勧めします。これは、名前が明確でデータを保持しない型引数を使用してコンストラクタをオーバーロードすることによって機能します。

struct clone_tag {}; 
class MyClass { 
public: 

    MyClass(int x, int y) : b_(x, y) {} 
    MyClass(const MyClass& self, clone_tag) : b_(self.b_, 10) {} 
private: 

    NotMyClass b_; 
}; 

int main() { 
    MyClass A(1, 2); 
    MyClass B(A, clone_tag()); 
} 

これは、建物の工場と最終的な建設が別々になっている本物の工場パターンまですることもできます。これは明らかにセットアップに時間がかかりますが、異なるコンストラクタパスの実際の数に応じてコードの品質を向上させることができます。二思想に

class MyClass { 
public: 
    struct Clone { 
     Clone(const MyClass& self) : self(self) {} 
     const MyClass& self; 
    }; 
    struct Init { 
     Init(int x, int y) : x(x), y(y) {} 
     int x, y; 
    }; 

    MyClass(Init i) : b_(i.x, i.y) {} 
    MyClass(Clone c) : b_(c.self.b_ , 10) {} 
private: 
    MyClass(const MyClass& other, int c) : b_(other.b_, c) {} 

    NotMyClass b_; 
}; 


int main() { 
    MyClass A = MyClass::Init(1, 2); 
    MyClass B = MyClass::Clone(A); 
} 

私は、3つの異なる選択肢を与えることあまり正確で短い答えよりも多くの混乱を引き起こす可能性があることを実現します。したがって、必要なリファクタリング作業の順番でリストアップしようとしましたが、これは実際のコードベースについての推測に過ぎません。

+0

いい考えですが、一時的なものはクローンのreturn文で構築できないと思います。なぜなら、MyClassのプライベートコピーコンストラクタを呼び出すからです。コピーコンストラクタはMyClass :: b_をコピーできません。なぜなら、コピーが不可能な 'NotMyClass ' – patatahooligan

+0

@patatahooliganあなたは私のコードを参照していますか?私はOPのコードのすべてが具体的に言及されている場合を除いてコンパイルされていると仮定していました。 – HeroicKatora

+0

私のコードは間違っていて、 'b_'がコピーされたと思っていましたが、実際は' b_(other.b_、c) 'として構築されています。 – patatahooligan

関連する問題