В C ++ существует концепция списка инициализации конструктора, где вы можете и должны вызывать конструктор базового класса, и где вы также должны инициализировать члены данных. Список инициализации следует после сигнатуры конструктора после двоеточия и перед телом конструктора. Допустим, у нас есть класс A:
class A : public B
{
public:
A(int a, int b, int c);
private:
int b_, c_;
};
Тогда, предполагая, что у B есть конструктор, который принимает int, конструктор A может выглядеть так:
A::A(int a, int b, int c)
: B(a), b_(b), c_(c) // initialization list
{
// do something
}
Как видите, конструктор базового класса вызывается в списке инициализации. Кстати, инициализация элементов данных в списке инициализации предпочтительнее, чем присвоение значений для b_ и c_ внутри тела конструктора, поскольку вы экономите дополнительную стоимость присваивания.
Имейте в виду, что члены данных всегда инициализируются в том порядке, в котором они объявлены в определении класса, независимо от их порядка в списке инициализации. Чтобы избежать странных ошибок, которые могут возникнуть, если ваши элементы данных зависят друг от друга, вы всегда должны следить за тем, чтобы порядок элементов был одинаковым в списке инициализации и определении класса. По той же причине конструктор базового класса должен быть первым элементом в списке инициализации. Если вы вообще его опустите, конструктор по умолчанию для базового класса будет вызываться автоматически. В этом случае, если базовый класс не имеет конструктора по умолчанию, вы получите ошибку компилятора.