Здравствуйте, Лазар Бешкенадзе, Вы писали:
ЛБ>На самом деле работают, более того, работают именно как виртуальные
ЛБ>Фразу, что я комментировал можно понимать как отключение виртуального механизма вызова и переход на статический при вызове виртуального метода из конструктора/деструктора.
Я, быть может, чего-то не понимаю, но для меня эти реплики не эквивалентны.
Что же касается моего утверждения о механизмах вызова, то тут я погорячился.
Стандарт требует, чтобы вызов (как приямой, так и опосредованный) виртуальной функции в конструкторе/деструкторе соответствовал прямому вызову "обычной" функции. Это просто сделать, когда имеет место прямой вызов (косвенно это подтверждает приведенный пример
), но в случае опосредованного вызова (как в твоем примере) все не так просто, и компилятору приходится идти на некоторые ухищрения, чтобы выполнить требования стандарта. Один из вариантов реализации этих самых ухищрений — использовать готовый механизм виртуального вызова через таблицу виртуальных функций. Единственное, что нужно сделать для обеспечения требуемого поведения — последовательно подменять указатель на таблицу виртуальных функций по мере создания/разрушения объекта. Однако в общем случае может быть использован другой механизм, и поэтому говорить о том, что вызов именно "виртуальный" — некорректно.
Любите книгу — источник знаний (с) М.Горький
Re[5]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, functional, Вы писали:
F>>Прямо говорится: К>
F>>...any direct or indirect call to an unimplemented pure virtual function from a constructor or destructor results in undefined behavior.
К>Прямой вызов виртуальной функции из ктора/дтора — статический. Если функция не определена (неважно, =0 она или нет), то получим не UB, а ошибку линковки.
Я встречал только один способ подавления виртуальности вызова в стандарте и это — явная квалификация 10.3 (12)
Если нет явной квалификации, вызов — виртуальный. А виртуальный вызов чисто виртуальной функции из ctor/dtor — undefined 10.4 (6)
Лазар
Re[3]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Лазар Бешкенадзе, Вы писали:
ЛБ>На самом деле работают, более того, работают именно как ЛБ>виртуальные, просто вызывается последний override на момент ЛБ>создания объекта класса исполняемого конструктора/деструктора.
Для интереса посмотрел, что делает MS VC++ 7.1:
class Base
{
public:
virtual void Foo() { }
void Bar() { }
virtual ~Base()
{
Foo(); // 3
Bar(); // 4
}
};
class Derived: public Base
{
public:
virtual void Foo() { }
};
int main()
{
Base* pb = new Derived();
pb->Foo(); // 1
pb->Bar(); // 2delete pb;
return 0;
}
Строчки (1) и (2) породили следующий машинный код:
Видно, что в первом случае вызов производится "виртуальный" вызов (т.е. адрес функции берется из таблицы виртуальных методов объекта), а во втором случае — "обычный", т.е. по известному заранее (на момент компиляции) адресу. В-общем ничего удивительного, все как и ожидается.
Теперь смотрим, что получилось из строчек (3), (4) (вызовов виртуальной и невиртуальной функций в деструкторе):
Как видно из этого листинга, ни о каком виртуальном вызове (в случае с Foo), тут речи и не идет. Адрес берется не из vtable, а уже известен на момент компиляции. Поэтому фраза "работают именно как виртуальные", как справедливо заметил Bell, совершенно несправедлива.
Кстати если Foo сделать в классе Base чисто виртуальной, то получим ошибки линковки:
Win32Console error LNK2019: unresolved external symbol "public: virtual void __thiscall Base::Foo(void)" (?Foo@Base@@UAEXXZ) referenced in function "public: virtual __thiscall Base::~Base(void)" (??1Base@@UAE@XZ)
Если при этом убрать вызов Foo из деструктора Base, но оставить этот же вызов в main(), то ошибки нет.
В-общем все это ИМХО говорит о том, что ни о какой виртуальности вызовов в конструкторе/деструкторе и речи не идет.
ЗЫ: насколько это согласуется со стандартом, не знаю.
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[8]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, ekamaloff, Вы писали:
E>Здравствуйте, Лазар Бешкенадзе, Вы писали:
E>[...]
E>Приведенный пример не в тему.
E>Речь шла о непосредственном вызове виртуальной функции из конструктора/деструктора, а не о косвенном (через другую функцию).
Ни в исходном сообщении, ни в сообщении на которое отвечал я, ни в стандарте
ничего не говорится о непосредственности.
E> И повторюсь, что оптимизация тут ни при чем, она была отключена в приведенном мной примере.
Отсюда не следует, что не делаются никакие оптимизации.
Проснись и пойми, что из того, что вызов сделан не через vtbl, не следует, что он невиртуальный.
Вот тебе пример непосредственного вызова:
#include <stdio.h>
struct A {
void sf() { ::printf("A::s\n"); }
virtual void vf() { ::printf("A::v\n"); }
};
struct B : A {
void sf() { ::printf("B::s\n"); }
virtual void vf() { ::printf("B::v\n"); }
};
struct C : B {
using A::sf;
using A::vf;
C() {
sf();
vf();
}
};
void main() { C(); }
Re[4]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, ekamaloff, Вы писали:
E>Как видно из этого листинга, ни о каком виртуальном вызове (в случае с Foo), тут речи и не идет. Адрес берется не из vtable, а уже известен на момент компиляции. Поэтому фраза "работают именно как виртуальные", как справедливо заметил Bell, совершенно несправедлива.
Концепция "работать как виртуальные" не обязана иметь какого-то отображенния на машинный код, порождаемый компилятором. На то она и концепция. Спецфикация языка требует, чтобы виртуальные методы, вызываемые (прямо или опосредованно) из конструкторов/деструкторов работали как виртуальные с той только оговоркой, что в качестве кандидатов на вызов рассматриваются только методы, определенные выше в иерархии классов, чем непосредственно конструируемый/деструктируемый класс. Это отличается от "полноценной" виртуальности, но этого в общем случае соврешенно не достаточно для того, чтобы отицать наличие виртуальность полностью.
Да, в случае непосредственного вызова виртуального метода из конструктора/деструктора конкретный целевой метод всегда можно определить на стадии компиляции. Соответсвенно, разумным будет сгенерировать код, который выполняет более эффективный прямой вызов. Точно также, как это можно делать вообще всегда, когда динамический тип объекта известен на стадии компиляции. Например, компиялтор иимете полное право сгенерировать код прямого вазова и в таких случаях:
CClass c;
c.some_virtual_method();
// Вызов виртуального метода. Практически любой компилятор странслирует в прямой вызов
// c.CClass::some_virtual_method();
CClass* pc = &c;
pc->some_virtual_method();
// "Умный" компилятор сообразит, что динамический тип '*pc' есть 'CClass' и генерирует прямой вызов
// pc->CClass::some_virtual_method()
Но на уровне языка вызовы от этого не перестают быть виртуальными. Остальное — детали реализации.
Best regards,
Андрей Тарасевич
Re: Почему не вызывается перегруженная виртуальная функция?
а вот не надо из конструкторов/деструкторов вызывать виртуальные функции.
в контрукторе базового наследник еще не создан.
в деструкторе базового -- уже разрушен.
такие дела.
Re: Почему не вызывается перегруженная виртуальная функция?
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Symon, Вы писали:
S>>Че это за бред такой???
J>А слабо было в поиске написать "виртуальная функция в деструкторе"?
Хорошо хоть не читайте Страуструпа
Re[2]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, Symon, Вы писали:
S>>Че это за бред такой??? B>Виртуальные вызовы не работают в конструкторах и деструкторе. Это обсуждалось не один раз.
На самом деле работают, более того, работают именно как
виртуальные, просто вызывается последний override на момент
создания объекта класса исполняемого конструктора/деструктора.
Лазар
Re[3]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Лазар Бешкенадзе, Вы писали:
ЛБ>На самом деле работают, более того, работают именно как ЛБ>виртуальные, просто вызывается последний override на момент ЛБ>создания объекта класса исполняемого конструктора/деструктора.
В моем понимании фраза "работают именно как виртуальные" подразумевает, что в общем случае механизмы вызова виртуальной и "обычной" функции в конструкторе/деструкторе могут отличаться. Если именно это имелось ввиду, то нельзя ли привести пример, иллюстрирубщий это утверждение? Если нет, то фраза "работают именно как виртуальные" лишена смысла, ИМХО.
Я что-то упустил?
Любите книгу — источник знаний (с) М.Горький
Почему не вызывается перегруженная виртуальная функция?
Здравствуйте, Symon, Вы писали:
J>>А слабо было в поиске написать "виртуальная функция в деструкторе"?
S>Хорошо хоть не читайте Страуструпа :)
Если бы ты задал этот вопрос ему, я думаю, такой ответ от него был бы вполне логичным.
Поиск на этом сайте сделан специально для того, чтобы людям не приходилось по сто раз отвечать на одни и те же вопросы.
Даже кнопочка есть: "Найти ответ".
Имей уважение к тем, к кому обращаешься за помощью, цени их время.
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, Лазар Бешкенадзе, Вы писали:
B>>>Виртуальные вызовы не работают в конструкторах и деструкторе. Это обсуждалось не один раз.
ЛБ>>На самом деле работают, более того, работают именно как ЛБ>>виртуальные, просто вызывается последний override на момент ЛБ>>создания объекта класса исполняемого конструктора/деструктора.
B>В моем понимании фраза "работают именно как виртуальные" подразумевает, что в общем случае механизмы вызова виртуальной и "обычной" функции в конструкторе/деструкторе могут отличаться. Если именно это имелось ввиду, то нельзя ли привести пример, иллюстрирубщий это утверждение? Если нет, то фраза "работают именно как виртуальные" лишена смысла, ИМХО. B>Я что-то упустил?
Фразу, что я комментировал можно понимать как отключение виртуального механизма вызова и переход на статический при вызове виртуального метода из конструктора/деструктора. Такая мысль звучала явно, например, в параллельном обсуждении:
Да, собственно, "в общем случае механизмы вызова виртуальной и "обычной" функции" отличаются и не только в конструкторе/деструкторе. Виртуальный вызов — он косвенный, что позволяет реализовать полиморфизм.
А вот и пример для вызова в конструкторе:
#include <stdio.h>
struct A {
void sf() { ::printf("A::sf\n"); }
virtual void vf() { ::printf("A::vf\n"); }
};
struct B : A {
void sf() { ::printf("B::sf\n"); }
virtual void vf() { ::printf("B::vf\n"); }
};
struct C : B {
C() {
((A *) this)->sf();
((A *) this)->vf();
}
};
void main() { C c; }
Лазар
Re[4]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, ekamaloff, Вы писали:
E>Здравствуйте, Лазар Бешкенадзе, Вы писали:
ЛБ>>На самом деле работают, более того, работают именно как ЛБ>>виртуальные, просто вызывается последний override на момент ЛБ>>создания объекта класса исполняемого конструктора/деструктора.
E>Для интереса посмотрел, что делает MS VC++ 7.1:
[snip] интересное исследование asm
E>Как видно из этого листинга, ни о каком виртуальном вызове (в случае с Foo), тут речи и не идет. Адрес берется не из vtable, а уже известен на момент компиляции. Поэтому фраза "работают именно как виртуальные", как справедливо заметил Bell, совершенно несправедлива.
А мы когда-нибудь слышали об оптимизации?
E>Кстати если Foo сделать в классе Base чисто виртуальной, то получим ошибки линковки:
E>
Win32Console error LNK2019: unresolved external symbol "public: virtual void __thiscall Base::Foo(void)" (?Foo@Base@@UAEXXZ) referenced in function "public: virtual __thiscall Base::~Base(void)" (??1Base@@UAE@XZ)
E>Если при этом убрать вызов Foo из деструктора Base, но оставить этот же вызов в main(), то ошибки нет.
Я уже писал, что если чисто виртуальную определить и вызвать напрямую, то может показаться, что работает.
Отсюда не следует, что поведение перестало быть undefined.
E>В-общем все это ИМХО говорит о том, что ни о какой виртуальности вызовов в конструкторе/деструкторе и речи не идет.
Вглядись в пример, что я привел в ответ на реплику Bell.
E>ЗЫ: насколько это согласуется со стандартом, не знаю.
HTH
Лазар
Re[5]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Лазар Бешкенадзе, Вы писали:
ЛБ>А мы когда-нибудь слышали об оптимизации?
Не думаю, что в данном случае имело место оптимизация
ЛБ>Вглядись в пример, что я привел в ответ на реплику Bell.
Ответ на реплику Bell совершенно не согласуется с вашей изначальной фразой:
более того, работают именно как
виртуальные, просто вызывается последний override на момент
создания объекта класса исполняемого конструктора/деструктора
Хотелось бы понять, что вы хотели этим сказать.
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[3]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Symon, Вы писали:
[...] S>Хорошо хоть не читайте Страуструпа
У Страуструпа это, кстати, трудно найти (я не нашел ) — но наверняка оно там есть
Проще разбираться по более поздней, "компилятивной" литературе. Например "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" (Herb Sutter, Andrei Alexandrescu).
Там Item 49 так и называется: Avoid calling virtual functions in constructors and destructors.
Прямо говорится:
...any direct or indirect call to an unimplemented pure virtual function from a constructor or destructor results in undefined behavior.
Успехов
Re[6]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, ekamaloff, Вы писали:
E>Здравствуйте, Лазар Бешкенадзе, Вы писали:
ЛБ>>А мы когда-нибудь слышали об оптимизации?
E>Не думаю, что в данном случае имело место оптимизация
ЛБ>>Вглядись в пример, что я привел в ответ на реплику Bell.
E>Ответ на реплику Bell совершенно не согласуется с вашей изначальной фразой:
E>
E>более того, работают именно как
E>виртуальные, просто вызывается последний override на момент
E>создания объекта класса исполняемого конструктора/деструктора
E>Хотелось бы понять, что вы хотели этим сказать.
По-моему здесь все ясно. Виртуальные вызовы виртуальных функций
делаются виртуально везде, в том числе и в ctor/dtor.
Это и демонстрирует пример.
Демонстрация оптимизированного компилятором кода в твоем сообщении
ничего не доказывает. Могу только привести еще один пример:
#include <stdio.h>
struct A {
virtual void v() { ::printf("A::v\n"); }
};
struct B : A {
B() { f(); }
void f() { v(); }
};
struct C : B {
virtual void v() { ::printf("C::v\n"); }
};
void main() { C().f(); }
Куда яснее?
Лазар
Re[7]: Почему не вызывается перегруженная виртуальная функци
Приведенный пример не в тему. Речь шла о непосредственном вызове виртуальной функции из конструктора/деструктора, а не о косвенном (через другую функцию). И повторюсь, что оптимизация тут ни при чем, она была отключена в приведенном мной примере.
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[4]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, functional, Вы писали:
F>Прямо говорится:
F>...any direct or indirect call to an unimplemented pure virtual function from a constructor or destructor results in undefined behavior.
Прямой вызов виртуальной функции из ктора/дтора — статический. Если функция не определена (неважно, =0 она или нет), то получим не UB, а ошибку линковки.
Перекуём баги на фичи!
Re[6]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, Лазар Бешкенадзе, Вы писали:
ЛБ>>На самом деле работают, более того, работают именно как виртуальные
ЛБ>>Фразу, что я комментировал можно понимать как отключение виртуального механизма вызова и переход на статический при вызове виртуального метода из конструктора/деструктора.
B>Я, быть может, чего-то не понимаю, но для меня эти реплики не эквивалентны.
B>Что же касается моего утверждения о механизмах вызова, то тут я погорячился. B>Стандарт требует, чтобы вызов (как приямой, так и опосредованный) виртуальной функции в конструкторе/деструкторе соответствовал прямому вызову "обычной" функции.
Вот чего требует стандарт:
12.7 (3)
... When a virtual function is called directly or indirectly from a constructor (including
from the mem-initializer for a data-member) or from a destructor, and the object to which
a call applies is the object under construction or destruction, the function called is the
one defined in the constructor or destructor's own class or in one of its bases, ...
Покажи, где тут говорится о каком-либо соответствии.
К тому же приведенный здесь пример
), но в случае опосредованного вызова (как в твоем примере) все не так просто, и компилятору приходится идти на некоторые ухищрения, чтобы выполнить требования стандарта. Один из вариантов реализации этих самых ухищрений — использовать готовый механизм виртуального вызова через таблицу виртуальных функций. Единственное, что нужно сделать для обеспечения требуемого поведения — последовательно подменять указатель на таблицу виртуальных функций по мере создания/разрушения объекта. Однако в общем случае может быть использован другой механизм, и поэтому говорить о том, что вызов именно "виртуальный" — некорректно.
Тут так все перевернуто с ног на голову, что мне остается только улыбнуться:
Лазар
Re[7]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Лазар Бешкенадзе, Вы писали: ЛБ>Вот чего требует стандарт:
ЛБ>12.7 (3) ЛБ>... When a virtual function is called directly or indirectly from a constructor (including ЛБ>from the mem-initializer for a data-member) or from a destructor, and the object to which ЛБ>a call applies is the object under construction or destruction, the function called is the ЛБ>one defined in the constructor or destructor's own class or in one of its bases, ...
ЛБ>Покажи, где тут говорится о каком-либо соответствии.
То, что ты привел — и есть правила для вызова обычной функции, если ты этого не заметил
ЛБ>К тому же приведенный здесь пример
явно показывал несоответствие.
Он показал лишь то, что используемый тобой компилятор выполняет вызов в соответствии с требованием стандарта, и ничего более. ЛБ>А тут еще один пример
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, Лазар Бешкенадзе, Вы писали: ЛБ>>Вот чего требует стандарт:
ЛБ>>12.7 (3) ЛБ>>... When a virtual function is called directly or indirectly from a constructor (including ЛБ>>from the mem-initializer for a data-member) or from a destructor, and the object to which ЛБ>>a call applies is the object under construction or destruction, the function called is the ЛБ>>one defined in the constructor or destructor's own class or in one of its bases, ...
ЛБ>>Покажи, где тут говорится о каком-либо соответствии. B>То, что ты привел — и есть правила для вызова обычной функции, если ты этого не заметил ЛБ>>К тому же приведенный здесь пример
явно показывал несоответствие. B>Он показал лишь то, что используемый тобой компилятор выполняет вызов в соответствии с требованием стандарта, и ничего более. ЛБ>>А тут еще один пример
Если ты имеешь ввиду void main(), то эта моя ошибка есть и в первом примере.
Я приношу глубочайшие извинения, переделывал ее из другой функции и оплошал.
Замени, пожалуйста, void на int — все скомпилируется.
ЛБ>>Тут так все перевернуто с ног на голову, что мне остается только улыбнуться: ЛБ>>
B>А у меня есть еще кое-что, кроме улыбок: B>предлагаю помедитировать над следующим примером
Тут нечего медитировать. Специально для тебя продолжение параграфа из стандарта.
Опять же приношу извинения, что первый раз поленился привести полностью.
12.7 (3)
... but not a function, overriding it in a class derived from the constructor
or destructor's class, or overriding it in one of the other base classes
of the most derived object.
Я, пожалуй, остановлюсь на этом, потому как ты говоришь на другом языке. Для
тебя вызов является виртуальным, если он идет через vtbl, а в стандарте просто
нет понятия vtbl. Правила для виртуальных функций описываются так, как в
приведенном параграфе.
Лазар
Re[10]: Почему не вызывается перегруженная виртуальная функц
Здравствуйте, Лазар Бешкенадзе, Вы писали:
ЛБ> ЛБ>Если ты имеешь ввиду void main(), то эта моя ошибка есть и в первом примере.
Нет, я имею ввиду использование using declaration:
7.3.3/14
...
The base class members mentioned by a using-declaration shall be visible
in the scope of at least one of the direct base classes of the class
where the using-declaration is specified.
...
Т.е. нельзя в C писать using A::sf, поскольку она скрыта в непосредственном базовом классе (т.е. в B).
ЛБ>>>Тут так все перевернуто с ног на голову, что мне остается только улыбнуться: ЛБ>>>
B>>А у меня есть еще кое-что, кроме улыбок: B>>предлагаю помедитировать над следующим примером
ЛБ>Тут нечего медитировать. Специально для тебя продолжение параграфа из стандарта. ЛБ>Опять же приношу извинения, что первый раз поленился привести полностью.
ЛБ>12.7 (3) ЛБ>... but not a function, overriding it in a class derived from the constructor ЛБ>or destructor's class, or overriding it in one of the other base classes ЛБ>of the most derived object.
Я читал этот пункт стандарта, но все равно спасибо.
ЛБ>Я, пожалуй, остановлюсь на этом, потому как ты говоришь на другом языке.
Да, похоже, что мы говорим на разных языках.
ЛБ>Для тебя вызов является виртуальным, если он идет через vtbl, а в стандарте просто ЛБ>нет понятия vtbl.
Я такого не говорил — наоборот, я говорил, что вызов виртуальной функции из конструктора может быть реализован через таблицу виртуальных функций (если виртуальный функции реализованы через таблицу).
ЛБ>Правила для виртуальных функций описываются так, как в приведенном параграфе.
С этим трудно спорить, однако эти правила немного отличаются от того, с чего начал ты:
На самом деле работают, более того, работают именно как
виртуальные, просто вызывается последний override на момент
создания объекта класса исполняемого конструктора/деструктора
Поясню свой пример, поскольку, как мне кажется, его смысл от тебя ускользнул:
в деструкторе D1 вызов vg приводит к вызову B::vg, хотя подобъект D2 еще жив, и таким образом последний override — это D2::vg.
Это поведение, естественно, соответствует правилам из 12.7/3, но никак не твоему "правилу последнего override — а".
Любите книгу — источник знаний (с) М.Горький
Re[6]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Bell, Вы писали:
Б>>На самом деле работают, более того, работают именно как виртуальные
ЛБ>>Фразу, что я комментировал можно понимать как отключение виртуального механизма вызова и переход на статический при вызове виртуального метода из конструктора/деструктора.
B>Что же касается моего утверждения о механизмах вызова, то тут я погорячился. B>Стандарт требует, чтобы вызов (как приямой, так и опосредованный) виртуальной функции в конструкторе/деструкторе соответствовал прямому вызову "обычной" функции.
Я не совсем понимаю почему это утверждение используется как аргумент при в пользу некоего "отсутствия виртуальности". Например, одним из применений полиморфизма в С++ является "уточнение" поведения некоторого невиртуального метода базового класса-"скелета алгоритма" путем предоставления конкретных реализаций виртуальных функций это базового класса в классе-наследнике
Эта функциональность будет прекрасно работать и при вызове метода 'Run()' из конструктора/деструктора класса-наследника с той только оговоркой, что виртуальные вызовы буду выполняться так, как будто динамический типом объекта является именно тот тип, чей конструктор/деструктор непосредственно работает в данный момент. Тем не менее вызовы виртуальных методов будут вести себя совершенно "виртуально" (с учетом предыдущей оговорки). Виртуальность никак не отрицается тем фактом, что опосредованный вызов виртуальных функций соответствует по своему эффекту их прямому вызову из конструктора/деструктора класса-наследника.
Изначальное утверждение Лазара было, по моему мнению, совершенно верным. Виртуальность в С++ работает из конструткоров/деструкторов "до уровня" непосредственно конструируемого/деструктируемого объекта. Именно этого требует спецификация языка. А как это реализовано -"прямыми" вызовами или "непрямыми" — это уже детали реализации. Спецификация не оперирует такими понятиями.
Best regards,
Андрей Тарасевич
Re[7]: Почему не вызывается перегруженная виртуальная функци
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Я не совсем понимаю почему это утверждение используется как аргумент при в пользу некоего "отсутствия виртуальности".
... АТ>Эта функциональность будет прекрасно работать и при вызове метода 'Run()' из конструктора/деструктора класса-наследника с той только оговоркой, что виртуальные вызовы буду выполняться так, как будто динамический типом объекта является именно тот тип, чей конструктор/деструктор непосредственно работает в данный момент.
Никто не доказывает "отсутсвие виртуальности". Более того, в одном из своих постов
я прямо говорил об использовании механизма виртуального вызова. Однако я не согласен с тем, что
...
На самом деле работают, более того, работают именно как виртуальные, просто вызывается последний override на момент создания объекта класса исполняемого конструктора/деструктора.
Пример, который я приводил, ИМХО достаточно красноречиво говорит о том, что это объяснение не верно.
Ну а твое объяснение (с учетом немаловожной, ИМХО, "оговорки") объясняет все правильно, впрочем как и обяснение "вызов виртуальной функции в конструкторе/деструкторе осуществляется по тем же правилам, что и прямой вызов "обычной" функции".