1

次の点を考慮してください。

class Foo {
public:
    Foo (const char *in) {
        printf ("C string constructor called\n");
    }
    Foo (std::string const &in) : Foo(in.c_str()) {
        printf ("C++ string constructor called\n");
    }
};
Foo bar ("I never asked for this");
//C string constructor called

したがって、定数stringは 1 として扱われconst char *ます。

std::stringしかし、コンストラクターを「プライマリ」にすると何が変わるでしょうか?

std::stringC 文字列関連のオブジェクトを呼び出さずに、オブジェクトが作成され、対応するコンストラクターに渡されると期待できますか?

class Foo {
public:
    Foo (std::string const &in) {
        printf ("C++ string constructor called\n");
    }
    Foo (const char *in) : Foo(std::string (in)) {
        printf ("C string constructor called\n");
    }
};
Foo bar ("I never asked for this");
//C++ string constructor called
//C string constructor called

繰り返しますが、C 文字列コンストラクターが最初に呼び出されました。

この動作は C++ 標準で説明されていますか、それともコンパイラ関連ですか?

これは、テンプレートやオーバーロードされた関数などでも同じように機能しますか?

GCC 7.3.0 (MSYS2 x64) でコンパイルしました。

4

3 に答える 3

1

オーバーロードの解決コンストラクターの委任は、互いにまったく影響を与えない 2 つの完全に異なるものです。

オーバーロードの解決は、可能な場合は暗黙的な変換を回避します。

のような文字列リテラル"I never asked for this"は aconst char[]に減衰しconst char *ます。これはコンストラクターと完全に一致するため、const char *それが呼び出されます。std::string入力として文字列リテラルを使用してコンストラクターを呼び出すには、コンパイラーが一時std::stringオブジェクトを構築して参照にバインドするため、暗黙的な変換が必要になりstd::string const &ます。

代わりにこのコードを書いていたら:

Foo bar (std::string("I never asked for this"));

またはこれ:

std::string str = "I never asked for this";
Foo bar (str);

次に、からへの暗黙的な変換がないため、コンストラクターstd::string const &の代わりにコンストラクターが呼び出されます。const char *std::stringconst char *

コンストラクターが互いに委任する方法は、コンパイラーが呼び出すコンストラクターを決定した後の実装の詳細です。

于 2018-06-20T17:13:20.653 に答える