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


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

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

1 68

1 ответ:

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

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

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

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

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

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

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

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