Как выяснилось, третий тип, complete object allocating constructor, никогда не используется. И на том спасибо, а то это была бы тайна трех конструкторов..
В терминологии gcc эти конструкторы называются in-charge и not-in-charge конструкторами. Разница между ними заключается в том, что not-in-charge конструктор конструирует только поля данного класса, не вызывая родительских конструкторов. В то время как in-charge конструктор конструирует объект полностью.
Использование в дочерних конструкторах not-in-charge конструкторов базовых классов позволяет избежать многочисленных инициализаций. Скорее всего это актуально для множественного наследования. Подробнее можно прочитать здесь.
Но проблема заключается в том, что в классе, у которого нету предков, эти конструкторы полностью идентичны. Их можно было бы представить в виде одного метода с двумя разными именами. Бага, не бага, но штука не очень хорошая.
Не знаю, как с этим обстоят дела в других компиляторах, но пользователям gcc, беспокоящимся об объеме своих программ можно дать такой рецепт: Минимизировать тело конструкторов. Все инициализационные рассчеты выносить в отдельные инициализационные методы.
Мне удалось избежать дублирования, описав тело конструктора в описании класса (inline конструктор), при этом он всеравно оформился в виде функции, но теперь уже однократно.
00000000 W _ZN15RandomGeneratorC1Ev
Вот пожалуй и все...
11 коммент.:
Хороший разбор вышел, интересно.
Ну для меня это было откровением. А особенно смутило что конструкторы абсолютно одинаковые и два. Если бы они сразу были разные - я бы быстрее сообразил, в какую сторону копать :)
Говорят вот, Watcom спокойно обходится одним конструктором.
Видимо особенность gcc.
А что за версия gcc?
chizh: У меня - gcc (GCC) 4.1.2 (Gentoo 4.1.2 p1.0.2)
У тебя такой феномен не проявляется? Ты на какой версии пишешь?
Не, это я чисто для себя спросил. Сам я уже давно ни чего не пишу, тем более на gcc.
Вообще я думаю, если все ключи и опции компилятора изучить, то что-нибудь в этом роде можно отыскать.
И по идее, если сделать конструктор в секции private, то ни каких копий не должно быть.
Ради интереса, пришли мне файл cpp с примером на akobets@mail.ru , проверю на версии gcc 4.2.2. Также есть смысл проверить на версии 4.3, там новый алгоритм компиляции.
Изменение области видимости на private не должно оказывать эффекта. а protected по идее должен, но не оказывает.
Вероятно gcc раздваивает все конструкторы без разбора, в этом то и заключается бага.
Теоретически protected конструкторы не могут быть использованы из потомков даже неявно (надо проверить).
Кроме того нет никакой необходимости раздваивать конструкторы для базовых объектов. Поведение конструкторов различается только у наследников.
Может более свежий gcc такие ситуации и разрулит.
А вот нихрена...
protected конструктор по умолчанию неявно всеравно вызывается.
Да и явно вызывается без малейших возражений...
странно это...
Попробовал на версии 4.2.2, точно такой же результат. Если знаешь английский, то можно задать
вопрос на форуме
http://groups.google.com/group/comp.lang.c++
или
http://groups.google.com/group/comp.unix.programmer
Да мне оно как-то не надо.
К тому же я не настолько знаю английский.
Главное для себя уяснить этот факт и пользоваться конструкторами и деструкторами осмотрительно.
Особенно в системном программировании... :)
Теоретически protected конструкторы не могут быть использованы из потомков даже неявно (надо проверить).Андрей! Это private-конструкторы не могут быть вызваны из потомков, а protected не могут быть вызваны вне класса и его потомка/потомков (если не указан friend для caller'а). Я даже проверил...
Два примера ниже корректно компилируются
-------------------------
class A {
protected:
A (int){}
};
class B : public A {
protected:
B (int a):A(a){}
};
-------------------------
class A {
protected:
A (int){}
};
class B : private A {
public:
B (int a):A(a){}
};
Примера ниже не компилируются
-------------------------
class A {
private:
A (int){}
};
class B : public A {
public:
B (int a):A(a){}
};
2icdm: А я уже не помню что хотел сказать, может быть и правда перепутал private и protected. :)
Отправить комментарий