2016-11-08 24 views
2

Plain English、Second Edition(1999)のC++には、正しいコンストラクタを呼び出す際に "="を使用して初期化を行うことができるセクションがあります。なぜこのC++メンバー初期化子リストは機能しませんか?

同様に、最終宣言は、コンストラクタCStr関数(文字*)を呼び出します:

CStr name3 = "Jane Doe"; 

私は同じことを試してみたかったクラスCStrとコンストラクタCStr(char*)与えられた、この本は、これは言うのようにstd::stringコンストラクタを持つもの。私はコンパイルすると、しかし、私はNAME3の初期化中にエラーが発生します

using namespace std; 
class CStr { 
private: 
    string name; 
public: 
    CStr(string s): name(s) {} 
}; 

int main() { 
    CStr name3 = "Jane Doe"; 
} 

非スカラへの「変換 『のconstのchar [9]』私のテストコードの一部は、このです'CStr'が要求されました。

なぜCStr :: nameを文字列s = "Jane Doe"で初期化しなかったのですか? string nameTest{"Jane Doe"};のような文字列テストが機能したので、これもうまくいくと思いました。たぶん本の古い(それは私が今持っている唯一の本です)、しかし私はエラーが私の部分にもっとあると思っています。

+2

Btw、C++は'99以降かなり変更されました。新しい機能のヒープを追加し、一度廃止された機能の一部を削除した2つの新しい標準がその後リリースされました。 –

+1

実際に私の机の上にその本のコピーがあります。非常に便利な本は、C標準ライブラリのクイックリファレンスとしての時間です。 – user4581301

+1

ところで、 'CStr(char *)'コンストラクタで文字列リテラルを使う時間はなくなりました。文字列リテラルはもはや 'char *'型に変換することはできず、 'const char *'のみに変換することができます。 – AnT

答えて

6

あなたの本は古いですが、基本的には右[1]です。 "Jane Doe"std::stringではなく、const char[9]です(また、const char*に減衰する可能性があります)。したがって、CStr name3 = "Jane Doe";の場合、2つのユーザー定義の変換が必要です(つまり、const char* - >std::stringおよびstd::string - >CStr)。これは1つでは許可されていません。implicit conversion

これは、CStrの構成がパラメータとしてconst char*を取ると、CStr name3 = "Jane Doe";がうまくいくことを示しています。これは、1つのユーザー定義の変換が必要なためです。

明示的な変換を追加することによって、いずれかを減らすことができる:

CStr name3 = std::string("Jane Doe"); 

または使用string literal(以降C++ 14)を直接、タイプstd::stringである:

CStr name3 = "Jane Doe"s; 

なぜCStr :: nameを文字列s = "Jane Doe"に初期化しなかったのですか? string nameTest{"Jane Doe"};のような文字列テストが機能したので、これもうまくいくと思いました。

あなたの質問は(1)一つだけ暗黙の変換(const char*std::string nameTest{"Jane Doe"};作品(、あなたの誤解によって異なります)、ので、とにかく、十分に明確ではありません - >std::stringが、ここで必要とされている;(2)string nameTest{"Jane Doe"};は直接初期化です。

@LightnessRacesinOrbitがコメントした通り、direct initialization(すなわちCStr name3 = "Jane Doe";copy initializationである(C++ 11以降)CStr name3("Jane Doe")又はCStr name3{"Jane Doe"})は、正常に動作するであろう、彼らはいくつかの点で異なっている:また

、コピー初期における暗黙の変換が から直接Tを生成しなければなりません初期化子、例えば、 直接初期化では、 イニシャライザからTのコンストラクタの引数への暗黙的な変換が必要です。

struct S { S(std::string) {} }; // implicitly convertible from std::string 
S s("abc"); // OK: conversion from const char[4] to std::string 
S s = "abc"; // Error: no conversion from const char[4] to S 
S s = "abc"s; // OK: conversion from std::string to S 

これはコピーの初期化のために、手段、const char*ある引数Jane Doeは、直接CStrに変換されなければなりません。 2つのユーザー定義の変換が必要なため、コードは拒否されます。直接初期化の場合はJane Doeconst char*)をCStrのコンストラクタの引数、つまりstd::stringに変換してから、CStr::CStr(std::string)を呼び出してオブジェクトを構築します。


[1] "Jane Doe"は、例えば、C++ 11からはchar*に代入することは違法だ、CONSTであるCスタイルstring literalあります

char * pc = "Jane Doe";   // illegal 
const char * pcc = "Jane Doe"; // fine 
+2

または 'Cstr name3(" Jane Doe ")'または 'CStr name3 {" Jane Doe "}' –

+0

あなたの答えは良いですが、パズルの欠けている部分は、コピー初期化が他の種類と異なる方法の1つです。 –

+0

@LightnessRacesinOrbit OPの誤解はどうやって私には分かりませんか?とにかく私は関連する説明を追加しようとしました。 – songyuanyao

関連する問題