108

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

惠普:

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

cp:

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 回答