пятница, 15 февраля 2008 г.

Еще немного про in-charge конструкторы...

Всравно, в этой истории много непонятного. Пытался выяснить для себя, чем же всетаки они должны отличаться. Понятное дело, что отличаться они должны где-то в дочерних методах. Ради эксперимента создал примерно такую иерархию:

class foo;
class bar : public foo;
class cut : public bar;


Или как там обычно называют третий класс для примера?

Компилирую - каждый дочерний класс вызывает in-charge конструктор родительского, причем из обоих своих конструкторов! При этом идентичность двух версий конструкторов сохраняется.

Предположив, что это как-то связано с таблицами виртуальных методов вношу виртуальные методы. И опять не вижу разницы... каждый из шести конструкторов честно ставит указатель на vtbl своего класса, И в чем тут соль - не понятно.

0804855a <_ZN3barC2Ev>:
804855a: 8b 44 24 04 mov 0x4(%esp),%eax
804855e: c7 00 70 86 04 08 movl $0x8048670,(%eax)
8048564: c3 ret

08048584 <_ZN3barC1Ev>:
8048584: 8b 44 24 04 mov 0x4(%esp),%eax
8048588: c7 00 70 86 04 08 movl $0x8048670,(%eax)
804858e: c3 ret

Но нету никакой разницы.
Вероятно стоит с этим вопросом всетаки обратиться в comp.lang.c++, или наверное еще лучше к кому нибудь из группы gcc.

Может быть множественое наследование???
class foo;
class bar;
class cut : public bar, public foo;


Но нет, опять никакой разницы... что-то я наверное не понимаю :)
Может быть содержимого прикрутить? Опять не то.

А-а-а, ЭВРИКА! нашел, нашел... :)
В случае виртуального наследования конструкторы получаются разными!

class foo;
class bar : virtual public foo;

08048522 <_ZN3barC1Ev>:
8048522: 8b 44 24 04 mov 0x4(%esp),%eax
8048526: c7 00 fc 85 04 08 movl $0x80485fc,(%eax)
804852c: c3 ret

08048514 <_ZN3barC2Ev>:
8048514: 8b 44 24 08 mov 0x8(%esp),%eax
8048518: 8b 10 mov (%eax),%edx
804851a: 8b 44 24 04 mov 0x4(%esp),%eax
804851e: 89 10 mov %edx,(%eax)
8048520: c3 ret


not-in-charge конструктор _ZN3barC1Ev не обращает внимания на виртуальность наследования, в то время как in-charge конструктор _ZN3barC2Ev получает два параметра (два указателя this вероятно), и похоже переписывает указатель на vtbl из родительского класса в свой, хотя я не использовал виртуальные функции а данном эксперименте, но видимо виртуальное наследование автоматически приводит к появлению vtbl.

Но помоему, виртуальное наследование используется не слишком часто, чтобы дапить конструкторы в любом случае. Неразумно как-то.