Вызывать виртуальный метод без указания на объект?
#include <iostream>
struct A {
void init()
{
internal_init();
}
virtual void internal_init()
{
std::cout << "internal of A" << std::endl;
}
};
struct B: public A {
void internal_init()
{
init();
std::cout << "internal of B" << std::endl;
}
};
int main(){
B instance;
std::cout << "internal of A" << std::endl;
instance.internal_init();
return 0;
}
Сначала программа идет в B::internal_init()
как и ожидалось. Затем, чтобы A::init()
(Я думаю, так как B происходит от A, а B не имеет каких-либо init()
). Что теперь?
какие internal_init()
это выберет? так как он идет к B::internal_init()
Программа войдет в бесконечный цикл, и я не понимаю почему.
- Что действительно происходит, когда я звоню
internal_init()
? - почему это вызывает
internal_init()
"B часть" экземпляра? Это о "виртуальном"? Если так, как получилось? Виртуальные функции имеют место, когда мы используем полиморфизм (который, насколько понимает начинающий, он работает с указателями базового класса, которые указывают на объекты производного класса).
2 ответа
Поскольку instance
это B
instance.internal_init();
Позвоню B
s internal_init()
, Затем в internal_init()
ты звонишь init();
, Теперь функции-члены имеют неявный параметр, который является указателем this.
Поэтому, когда мы звоним A
"s init()
этот указатель на самом деле B
, В init()
мы называем internal_init();
используя этот указатель на B
, поскольку internal_init()
является виртуальным, и у нас есть указатель на B
механизм виртуального поиска будет вызывать B
"s internal_init()
,
Затем этот цикл повторяется снова и в конечном итоге вызывает переполнение сегмента или переполнение стека.
Во -первых struct B
наследует все функции struct A
потому что struct B: public A
, Функция internal_init
из A
переопределяется в B
потому что вы используете одну и ту же сигнатуру функции и ключевое слово virtual
в A
,
Так что теперь звонки:instance.internal_init();
какие звонки internal_init()
из B
, который вызывает A::init
, который вызывает B::internal_init()
и т. д., пока не дается ошибка сегментации. Чтобы предотвратить это (и я думаю, что это то, что вы хотите), вы можете явно вызвать internal_init()
из A
в B
вместо звонка init()
:
struct B: public A {
virtual void internal_init()
{
A::internal_init();
std::cout << "internal of B" << std::endl;
}
};