Инициализация члена при использовании делегированного конструктора

Я начал опробовать стандарт C++11 и нашел этот вопрос, который описывает, как вызывать ваш ctor из другого ctor в том же классе, чтобы избежать использования метода init или чего-либо подобного. Теперь я пытаюсь сделать то же самое с кодом, который выглядит следующим образом:

HPP:

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

каст:

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; вместо этого и работает нормально. Но я бы очень хотел иметь возможность использовать список инициализатора.

Заранее спасибо!

1 ответ

Решение

Когда вы делегируете инициализацию члена другому конструктору, есть предположение, что другой конструктор полностью инициализирует объект, включая все члены (т.е. включая lines участник в вашем примере). Поэтому вы не можете снова инициализировать ни одного из участников.

Соответствующая цитата из Стандарта (выделено мной):

(§12.6.2 / 6) Список mem-initializer-list может делегировать другому конструктору класса конструктора, используя любой класс-или-decltype, который обозначает сам класс конструктора. Если mem-initializer-id обозначает класс конструктора, он должен быть единственным mem-initializer; конструктор является делегирующим конструктором, а выбранный конструктор является целевым конструктором. [...]

Вы можете обойти это, определив версию конструктора, который сначала принимает аргументы:

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

а затем определить конструктор по умолчанию, используя делегирование:

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

Как правило, вы должны полностью указать ту версию конструктора, которая принимает наибольшее количество аргументов, а затем делегировать из других версий (используя требуемые значения по умолчанию в качестве аргументов в делегировании).

Другие вопросы по тегам