108

私は C++11 標準を試し始めましたが、同じクラスの別の ctor から ctor を呼び出して init メソッドなどを使用しないようにする方法を説明するこの質問を見つけました。今、私は次のようなコードで同じことを試みています:

馬力:

class Tokenizer
{
public:
  Tokenizer();
  Tokenizer(std::stringstream *lines);
  virtual ~Tokenizer() {};
private:
  std::stringstream *lines;
};

cpp:

Tokenizer::Tokenizer()
  : expected('=')
{
}

Tokenizer::Tokenizer(std::stringstream *lines)
  : Tokenizer(),
    lines(lines)
{
}

しかし、これは私にエラーを与えています: In constructor ‘config::Tokenizer::Tokenizer(std::stringstream*)’: /path/Tokenizer.cpp:14:20: error: mem-initializer for ‘config::Tokenizer::lines’ follows constructor delegationリストの最初と最後に Tokenizer() 部分を移動しようとしましたが、それは役に立ちませんでした。

この背後にある理由は何ですか?どうすれば修正できますか? 代わりに をlines(lines)本体に移動しようとしましたが、正常に動作します。this->lines = lines;しかし、イニシャライザリストを使用できるようにしたいと本当に思っています。

4

1 に答える 1

134

メンバーの初期化を別のコンストラクターに委任すると、他のコンストラクターがすべてのメンバーを含めてオブジェクトを完全linesに初期化するという前提があります (つまり、例のメンバーを含む)。したがって、メンバーを再度初期化することはできません。

標準からの関連する引用は次のとおりです(強調鉱山):

(§12.6.2/6) mem-initializer-list は、コンストラクターのクラス自体を示す任意の class-or-decltype を使用して、コンストラクターのクラスの別のコンストラクターに委任できます。mem-initializer-id がコンストラクターのクラスを指定する場合、それが唯一の mem-initializer になります。コンストラクターは委任コンストラクターであり、によって選択されたコンストラクターはターゲット コンストラクターです。[...]

最初に引数を取るコンストラクターのバージョンを定義することで、これを回避できます。

Tokenizer::Tokenizer(std::stringstream *lines)
  : lines(lines)
{
}

次に、委任を使用してデフォルトのコンストラクターを定義します。

Tokenizer::Tokenizer()
  : Tokenizer(nullptr)
{
}

原則として、最大数の引数を取るコンストラクターのバージョンを完全に指定してから、他のバージョンから委任する必要があります (委任の引数として目的の既定値を使用します)。

于 2012-08-30T04:55:13.910 に答える