C++ Полиморфизм. Почему это работает?
Разве это не должно быть неправильно?:
A* apb = (A*)&b; //a pointer to b
Я ожидаю ошибку или, по крайней мере, предупреждение.
Почему это не дает мне никакого предупреждения ни в Visual C++ 2013 (v120), ни в g++ (gcc 4.8.2)?
#ifndef A_H
#define A_H
#include <stdio.h>
class A
{
public:
A(){}
virtual ~A(){}
void print(){ printf("printA\n"); }
virtual void printVirtual(){ printf("printVirtualA\n"); }
};
#endif // A_H
#ifndef B_H
#define B_H
#include "A.hpp"
class B : A
{
public:
B(){}
void print(){ printf("printB\n"); }
virtual void printVirtual(){ printf("printVirtualB\n"); }
};
#endif //B_H
int main()
{
A a;
B b;
A* apb = (A*)&b; //a pointer to b
B* bpa = (B*)&a; //b pointer to a
apb->print(); // printA
apb->printVirtual(); // printVirtualB
bpa->print(); // printB
bpa->printVirtual(); // printVirtualA
return 0;
}
Выход:
printA
printVirtualB
printB
printVirtualA
Я подозреваю, что это потому, что мои классы выровнены в памяти, так что есть действительный Vtable.
Это "неявный" dynamic_cast?
Из того, что я узнал, не следует делать это правильно.
3 ответа
Это именно то, для чего нужны vtables. не виртуальные функции вызываются в соответствии с типом контейнера, а виртуальные функции вызываются в соответствии с типом указанного объекта.
A* apb = (A*) &b;
.... это прекрасный код и классический пример виртуального полиморфизма.
A* apb = (A*) &b;
Это совершенно нормально. Базовый указатель, указывающий на удаленный объект. За этой схемой в большинстве случаев следуют абстрактные классы (или интерфейсы) для возможного полиморфизма
A* apb = (A*)&b;
Это нормально, чтобы инициализировать указатель базового класса из производного класса (предполагается b
имеет тип B
как ты показываешь). Вам даже не нужна операция приведения
A* apb = &b;
void print()
функции-члены не помечены virtual
таким образом, функции-члены вызываются на фактическом экземпляре, который у вас есть.