Есть ли (практический) способ обходить нормальный (виртуальный) порядок вызова конструктора?
Пример:
class A
{
const int i;
public:
A()
: i(0)
{ cout << "calling A()" << endl; }
A(int p)
: i(p)
{ cout << "calling A(int)" << endl; }
};
class B
: public virtual A
{
public:
B(int i)
: A(i)
{ cout << "calling B(int)" << endl; }
};
class C
: public B
{
public:
C(int i)
: A(i), B(i)
{ cout << "calling C(int)" << endl; }
};
class D
: public C
{
public:
D(int i)
: /*A(i), */ C(i)
{ cout << "calling D(int)" << endl; }
};
int main()
{
D d(42);
return 0;
}
Вывод:
вызов A()
вызов B (int)
вызов C (int)
вызов D (int)
Я хочу иметь что-то вроде:
вызов A (int)
вызов B (int)
вызов C (int)
вызов D (int)
Как вы видите, существует виртуальное наследование, которое приводит к тому, что конструктор D вызывает конструктор A сначала, но поскольку параметр не указан, он вызывает A(). Там const int i, который нуждается в инициализации, поэтому у меня есть проблема.
Что я хотел бы сделать, так это скрыть детали наследования C, поэтому я ищу способ избежать вызова A (i) в D (и каждый производный) список инициализации конструктора. [edit] В этом конкретном случае я могу предположить, что существуют только не виртуальные однонаследованные дочерние классы C (как D - один). [/Править]
[править]
Виртуальные базовые классы инициализируются до инициализации любых не виртуальных базовых классов, поэтому только самый производный класс может инициализировать виртуальные базовые классы. - Джеймс Макнеллис
Точно так, я не, хочу, чтобы самый производный класс вызывал конструктор виртуального базового класса. [/править]
Рассмотрим следующую ситуацию (не представлен в примере кода выше):
A
/ \
B0 B1
\ /
C
|
D
Я понимаю, почему C должен вызывать ctor A (двусмысленность) при создании экземпляра C, но почему D должен вызывать его при создании D?