2016-11-14 6 views
0

は、次のように私は不変Stringクラスがあるとします。オーバーロードの解決:明示的および初期化構文の役割は何ですか?

#include <iostream> 
#include <string> 

class String 
{ 
public: 
    explicit String(const char *Value) : Size(std::strlen(Value)), Value(new char[Size + 1]) 
    { 
     std::memcpy(this->Value, Value, Size + 1); 
     std::cout << Value << ", novice." << Size << std::endl; 
    } 
    template <typename T, std::size_t N> String(const T (&Value)[N]) : Size(N - 1), Value(new char[N]) 
    { 
     std::memcpy(this->Value, Value, N); 
     std::cout << Value << ", expert." << Size << std::endl; 
    } 
    ~String() 
    { 
     delete[] Value; 
    } 
private: 
    const std::size_t Size; 
    char *Value; 
}; 

void main() 
{ 
    auto &s = "Welcome to C++"; 
    String string = s; 
    String str {s}; 
    String st(s); 
    return; 
} 

は私が役割explicit演劇やどのようにコンストラクタのオーバーロードが選択されたときに初期化構文が違いを知ってほしいです。

私は strstのために、私は明示的に const charへのポインタを取るコンストラクタを呼び出していますので、彼らは、プリントアウトすることを理解

Welcome to C++, novice. 
Welcome to C++, novice. 

しかし、私はstring

のために理由を理解していません
Welcome to C++, expert. 

が印刷されます。過負荷がどのように選択されているかを明確にしてください。

String str {s}; 
String st(s); 

explicit String(const char *Value) 

+0

文字列クラスは、別の不変のCスタイルの文字列で初期化する場合にのみ変更できます。定数の配列が不変で、その配列から 'String'オブジェクトを作成しても、配列を変更することはできますし、おそらく不変な' String'オブジェクトも変更されます。 –

+0

私はそれを今すぐ実現しました。ありがとう! –

+2

@BoPersson私は嘘が正しいとは思わない。それは部分を演じますが、ここにも他のことが起こっています。 – NathanOliver

答えて

1

それがテンプレートではないので、ポインタ過負荷が選択される理由です。ポインタコンストラクタと配列コンストラクタの両方がsと完全に一致すると見なされるため、あいまいになりますが、配列コンストラクタはテンプレートであるため、ポインタコンストラクタとのマッチングはあまり考慮されません。 explicitを削除しても、ポインタの過負荷が選択されます。 sStringではないので

String string = s; 

explicitと今

は問題ありません。これは、コンパイラがそれを暗黙的に1に変換する必要があるため、配列コンストラクタを完全一致として選択し、明示的コンストラクタとして実行可能なコンストラクタのみを暗黙的変換で使用できないことを意味します。

+0

ポインタがオーバーライドされているのは、 'explicit'がないと、テンプレート化されていないためです。 –

+1

@AnirbanSarkarはい、テンプレートの方が優先順位が低いため、ポインタコンストラクタです。 – NathanOliver

+0

説明していただきありがとうございます。 –

関連する問題