Ответ 1
Когда вы делегируете инициализацию члена другому конструктору, существует предположение, что другой конструктор полностью инициализирует объект, включая всех членов (т.е. включая член lines
в вашем примере). Поэтому вы не можете снова инициализировать кого-либо из членов.
Соответствующая цитата из Стандарта (внимание мое):
(§12.6.2/6) Список mem-initializer может делегировать другому конструктору класса конструкторов, используя любой класс или-decltype, который обозначает сам класс конструкторов. Если mem-initializer-id обозначает класс конструкторов, он должен быть единственным mem-инициализатором; конструктор - это делегирующий конструктор, а конструктор, выбранный конструктором-мишенью. [...]
Вы можете обойти это, указав версию конструктора, которая сначала принимает аргументы:
Tokenizer::Tokenizer(std::stringstream *lines)
: lines(lines)
{
}
а затем определите конструктор по умолчанию, используя делегирование:
Tokenizer::Tokenizer()
: Tokenizer(nullptr)
{
}
Как правило, вы должны полностью указать ту версию конструктора, которая принимает наибольшее количество аргументов, а затем делегировать из других версий (используя требуемые значения по умолчанию в качестве аргументов в делеции).