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таким образом, функции-члены вызываются на фактическом экземпляре, который у вас есть.

Другие вопросы по тегам