使用委托构造函数时的成员初始化

lfx*_*ove 87 c++ gcc ctor-initializer c++11

我已经开始尝试C++ 11标准,我发现这个问题描述了如何从同一个类中的另一个ctor调用你的ctor以避免使用init方法等.现在我正在使用看起来像这样的代码尝试相同的事情:

HPP:

class Tokenizer
{
public:
  Tokenizer();
  Tokenizer(std::stringstream *lines);
  virtual ~Tokenizer() {};
private:
  std::stringstream *lines;
};
Run Code Online (Sandbox Code Playgroud)

CPP:

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

Tokenizer::Tokenizer(std::stringstream *lines)
  : Tokenizer(),
    lines(lines)
{
}
Run Code Online (Sandbox Code Playgroud)

但是这给了我错误: 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;相反的方式移动到身体,它工作正常.但我真的希望能够使用初始化列表.

提前致谢!

jog*_*pan 107

将成员初始化委托给另一个构造函数时,假设其他构造函数完全初始化对象,包括所有成员(即包括lines示例中的成员).因此,您无法再次初始化任何成员.

标准的相关引用是(强调我的):

(§12.6.2/ 6)mem-initializer-list可以使用任何表示构造函数类本身的class-or-decltype委托给构造函数类的另一个构造函数.如果mem-initializer-id指定构造函数的类,它应该是唯一的mem-initializer ; 构造函数是委托构造函数,由它选择的构造函数是目标构造函数.[...]

您可以通过定义首先获取参数的构造函数的版本来解决此问题:

Tokenizer::Tokenizer(std::stringstream *lines)
  : lines(lines)
{
}
Run Code Online (Sandbox Code Playgroud)

然后使用委托定义默认构造函数:

Tokenizer::Tokenizer()
  : Tokenizer(nullptr)
{
}
Run Code Online (Sandbox Code Playgroud)

作为一般规则,您应该完全指定获取最大数量参数的构造函数的版本,然后从其他版本委派(使用所需的默认值作为委托中的参数).

  • 一开始看起来反直觉,但实际上真的有帮助! (2认同)