Здравствуйте, PVA, Вы писали:
PVA>Интересует почему в случае с leaf нужный конструктор derived(name) вызывается, но инициализации base не происходит? PVA>p.s. Что инициализировать нужно базу — это знаю Вопрос исключительно теоретический.
Если "знаю", то тогда я не совсем понимаю, в чем именно вопрос. Почему так сделано? Потому что такого поведения требует спецификация языка.
Best regards,
Андрей Тарасевич
Re: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, PVA, Вы писали:
PVA>Интересует почему в случае с leaf нужный конструктор derived(name) вызывается, но инициализации base не происходит?
Виртуальную базу должен инициализировать most-derived класс.
Любите книгу — источник знаний (с) М.Горький
Re[2]: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, Андрей Тарасевич, Вы писали:
PVA>>Интересует почему в случае с leaf нужный конструктор derived(name) вызывается, но инициализации base не происходит? PVA>>p.s. Что инициализировать нужно базу — это знаю Вопрос исключительно теоретический.
АТ>Если "знаю", то тогда я не совсем понимаю, в чем именно вопрос. Почему так сделано? Потому что такого поведения требует спецификация языка.
Вопрос в том, почему вот здесь
derived() : base(name) {}
тело отрабатывает, а список инициализации игнорируется?
Например, если я инициалищацию перенесу в тело конструктора — свойство будет проинициализировано.
newbie
Re[2]: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, Bell, Вы писали:
PVA>>Интересует почему в случае с leaf нужный конструктор derived(name) вызывается, но инициализации base не происходит? B>Виртуальную базу должен инициализировать most-derived класс.
См. PS
newbie
Re: Еще раз о виртуальной базе при одиночном наследовании
PVA>Интересует почему в случае с leaf нужный конструктор derived(name) вызывается, но инициализации base не происходит?
Как это — нужный конструктор вызывается, но инициализация не происходит ?
Инициализация по вашему это что, кроме как не вызов конструктора ?
На самом деле вызов конструктора base НЕ будет производиться из вызова конструктора derived,
все вызовы конструкторов виртуальных баз должны быть ЯВНО прописаны в каждом из наследников, потому что по дереву наследования, поскольку есть несколько путей к предку, невозможно однозначно определить место, в котором должен следовать вызов конструктора виртуалной базы в порядке следования вызовов конструкторов предков.
Re[3]: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, PVA, Вы писали:
B>>Виртуальную базу должен инициализировать most-derived класс. PVA>См. PS
Ок, еще раз:
Виртуальную базу инициализирует most-derived класс. Это значит, что при конструировании объекта leaf сигнатура вызываемого конструктора base определяется в конструкторе класса leaf, а не derived. Поскольку в списке инициализации leaf отсутсвует упоминание base, для конструирования подобъекта base будет выбран конструктор по умолчанию. При этом совершенно не важно, что для конструирования derived указан конструктор с параметром. derived в данном случае не является most-derived классом, и компиятору совершенно безразлично то, какой контсруктор для base указан в конструкторе derived.
Любите книгу — источник знаний (с) М.Горький
Re[4]: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, MasterZiv, Вы писали:
PVA>>Интересует почему в случае с leaf нужный конструктор derived(name) вызывается, но инициализации base не происходит?
MZ>Как это — нужный конструктор вызывается, но инициализация не происходит ? MZ>Инициализация по вашему это что, кроме как не вызов конструктора ?
Попробую еще детальней
1. Происходит вызов base() — чудненько, base constructed
2. Происходит вызов параметризированного конструктора derived(const char * name), у которого параметром идет переданная строка "WTF?"
Дальше не интересно. Интересно, почему игнорируется вызов : base(name) из списка инициализации derived(...)?
MZ>На самом деле вызов конструктора base НЕ будет производиться из вызова конструктора derived,
Вот в этом и вопрос — почему?
MZ>все вызовы конструкторов виртуальных баз должны быть ЯВНО прописаны в каждом из наследников, потому что по дереву наследования, поскольку есть несколько путей к предку, невозможно однозначно определить место, в котором должен следовать вызов конструктора виртуалной базы в порядке следования вызовов конструкторов предков.
Совершенно с этим согласен и не спорю.
В целом можно считать вопрос закрытым. Странно, что компилер даже ворниг не выдает.
newbie
Re[5]: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, PVA, Вы писали:
PVA>Попробую еще детальней PVA>1. Происходит вызов base() — чудненько, base constructed PVA>2. Происходит вызов параметризированного конструктора derived(const char * name), у которого параметром идет переданная строка "WTF?" PVA>Дальше не интересно. Интересно, почему игнорируется вызов : base(name) из списка инициализации derived(...)?
Потому что base уже сконструирован, и конструктор для base был выбран в конструкторе leaf.
MZ>>На самом деле вызов конструктора base НЕ будет производиться из вызова конструктора derived, PVA>Вот в этом и вопрос — почему?
Потому что derived не является most-derived классом (я это уже не в первый раз повторяю).
PVA>В целом можно считать вопрос закрытым.
Как Вам угодно.
PVA>Странно, что компилер даже ворниг не выдает.
Какое предупреждение, по Вашему, должен был выдать компилятор?
Любите книгу — источник знаний (с) М.Горький
Re[4]: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, PVA, Вы писали:
PVA>Здравствуйте, Андрей Тарасевич, Вы писали:
PVA>>>Интересует почему в случае с leaf нужный конструктор derived(name) вызывается, но инициализации base не происходит? PVA>>>p.s. Что инициализировать нужно базу — это знаю Вопрос исключительно теоретический.
АТ>>Если "знаю", то тогда я не совсем понимаю, в чем именно вопрос. Почему так сделано? Потому что такого поведения требует спецификация языка. PVA>Вопрос в том, почему вот здесь PVA>
derived() : base(name) {}
PVA>тело отрабатывает, а список инициализации игнорируется?
Я по-прежнему не понимаю. Что значит "почему"? В спецификации языка ясно сказано, что виртуальные базы инициализирует "финальный" класс, т.е. что промежуточные классы-наследники не должны инициализировать свои виртуальные базы, независимо от того, что там написано в списке инициализации.
Компиляторы обязаны удовлетворить этому требованию спецификации. Как они будут ему удовлетворять — это уже их личное дело. Можно преположить множество разных способов. Например, компилятор может генерировать две версии конструктора 'derived::derived(const char *)'. Одна версия "нормальная", вызывается при конструировании самостоятельных объектов 'derived' ('d' в твоем примере). Другая версия "урезанная", не производящая инициализации виртуальных баз. Эта "урезанная" версия вызвается из конструктора класса 'leaf'. Вот и все.
Компиляотр может поступить еще как-нибудь по-другому. Например, неявно передавать в конструктор булевский флаг — инициализировать/не инициализировать виртуальные базы. В общем, способов много...
Best regards,
Андрей Тарасевич
Re[4]: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, Bell, Вы писали:
PVA>>Дальше не интересно. Интересно, почему игнорируется вызов : base(name) из списка инициализации derived(...)? B>Потому что base уже сконструирован, и конструктор для base был выбран в конструкторе leaf. MZ>>>На самом деле вызов конструктора base НЕ будет производиться из вызова конструктора derived, PVA>>Вот в этом и вопрос — почему? B>Потому что derived не является most-derived классом (я это уже не в первый раз повторяю).
С технической точки зрения это равносильно пропуску вызова функции.
PVA>>Странно, что компилер даже ворниг не выдает. B>Какое предупреждение, по Вашему, должен был выдать компилятор?
warning XXXX: "список инициализации объекта leaf будет проигнорирован"
newbie
Re[5]: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, PVA, Вы писали:
PVA>С технической точки зрения это равносильно пропуску вызова функции.
Никакого пропуска нет. Есть особенность, определяющая, какой именно конструктор нужно вызвать.
PVA>>>Странно, что компилер даже ворниг не выдает. B>>Какое предупреждение, по Вашему, должен был выдать компилятор? PVA>warning XXXX: "список инициализации объекта leaf будет проигнорирован"
Он-то как раз и не игнорируется, и конструктор для base определяется именно в списке инициализации leaf. "Игнорируется" вызов конструктора base с параметром в конструкторе derived.
А вообще указание конструктора предка в списке инициализации не есть вызов — это просто указаение компилятору, какой именно конструктор предка использовать при конструировании потомка (читай при построении цепочки вызовов).
В случае с виртуальным наследованием это указание игнорируется для промежуточных классов, вот и все.
Любите книгу — источник знаний (с) М.Горький
Re[6]: Еще раз о виртуальной базе при одиночном наследовании
Здравствуйте, Bell, Вы писали:
PVA>>С технической точки зрения это равносильно пропуску вызова функции. B>Никакого пропуска нет. Есть особенность, определяющая, какой именно конструктор нужно вызвать.
У меня посылки были:
1. конструктор всего-лишь функция инициализации данных.
2. всегда думал, что
derived(A a, B b) : a_(a), b_(b) {}
равносильно
derived(A a, B b) { a_ = a; b_ = b; }
Соответственно:
derived(const char * name) : base(name) { /* body */ } == derived() { base(name); /* body */ }
PVA>>>>Странно, что компилер даже ворниг не выдает. B>>>Какое предупреждение, по Вашему, должен был выдать компилятор? PVA>>warning XXXX: "список инициализации объекта leaf будет проигнорирован" B>Он-то как раз и не игнорируется, и конструктор для base определяется именно в списке инициализации leaf. "Игнорируется" вызов конструктора base с параметром в конструкторе derived.
Да, несомненно. Вот об этом надо было бы и выдать варнинг (сменим табличку): "список инициализации объекта leaf отсутствует. Будет использован конструктор по умолчанию"
B>А вообще указание конструктора предка в списке инициализации не есть вызов — это просто указаение компилятору, какой именно конструктор предка использовать при конструировании потомка (читай при построении цепочки вызовов).
Кхм. Цепочки вызовов чего?
B>В случае с виртуальным наследованием это указание игнорируется для промежуточных классов, вот и все.
Вы даже лучше меня строку для варнинга сочинили :D