web-dev-qa-db-ja.com

明示的なコピーコンストラクタ

Std :: stringを拡張して、カスタム関数ビルドをCustomStringという文字列クラスに書き込む必要があるというニーズを満たしました。

コンストラクターを定義しました:

    class CustomString : public std::string {
    public:
        explicit CustomString(void);
        explicit CustomString(const std::string& str);
        explicit CustomString(const CustomString& customString);
        //assignment operator
        CustomString& operator=(const CustomString& customString);
    ... };

3番目のコンストラクター(コピーコンストラクター)と代入演算子。その定義は次のとおりです。

CustomString::CustomString(const CustomString& customString):
    std::string(static_cast<std::string>(customString)) 
{}
CustomString& CustomString::operator=(const CustomString& customString){
    this->assign(static_cast<std::string>(customString));
    return *this;
}

まず、これは「明示的」であるためです。つまり、別のCustomStringオブジェクトに割り当てるには明示的なキャストが必要です。それは割り当てについて不平を言っています。

CustomString s = CustomString("test");

キャストが明示的に必要な場所が正確にわからない。

コピーコンストラクターが明示的でない場合、コードは正常に機能しますが、「適切なキャストを推測する」のではなく、明示的な定義を知り、実装したいと思います。

15
abumusamq

明示的なコピーコンストラクターは、コピーコンストラクターが暗黙的に呼び出されないことを意味します。これは、式で発生することです。

CustomString s = CustomString("test");

この式は文字通り、次のことを意味します。const char*をとるコンストラクターを使用して一時的なCustomStringを作成します。 CustomStringのコピーコンストラクターを暗黙的に呼び出して、その一時的なものからsにコピーします。

これで、コードが正しい場合(つまり、コピーコンストラクターが明示的でない場合)、コンパイラーは一時的なものの作成を回避し、文字列リテラルを使用してsを直接作成することでコピーを削除します。ただし、コンパイラは、構築が実行可能であり、そこで失敗することを確認する必要があります。

コピーコンストラクタを明示的に呼び出すことができます。

CustomString s( CustomString("test") );

ただし、一時的なものは完全に避け、const char*を使用してsを作成することをお勧めします。

CustomString s( "test" );

とにかくコンパイラが行うことはどれですか...

Std :: stringには仮想デストラクタがないため、std :: stringからの派生は安全ではありません。あなたの質問に関して-あなたのコピーコンストラクタは、次のような使用法を可能にするために、明示的であってはなりません:

CustomString s = "test";

また、コピーコンストラクターを明示的に宣言する必要がないので、なぜそれを宣言したいのかわかりません。明示的なコピーコンストラクターは、CustomStringオブジェクトを次のように宣言した場合にのみ機能します。

CustomString s(CustomString("test"));
6
ForEveR