Инициализация члена при использовании делегированного конструктора
Я начал опробовать стандарт 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)
{
}
Как правило, вы должны полностью указать ту версию конструктора, которая принимает наибольшее количество аргументов, а затем делегировать из других версий (используя требуемые значения по умолчанию в качестве аргументов в делегировании).