【发布时间】:2014-11-21 05:19:50
【问题描述】:
这不应该是不正确的吗? :
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 吗?
据我所知,这样做不应该是正确的。
【问题讨论】:
-
您正在强制编译器使用 C 风格的转换进行转换,所以它不会抱怨。哎呀,你可以做
float* bad = (float*)&b;,编译器仍然不会抱怨。但这并不能使它有效。我相信你的演员都不合法(B私下继承自A,而A不是从B派生的)。 -
向下转型呢?
B* bpa = (B*)&a; //b pointer to a是不是因为类有相同的结构才能正确执行? -
这实际上是未定义的行为并且是非法的。但是,它似乎可以工作,因为
A和B是非常简单的类(它们没有成员,并且这些函数只是打印文本而不做任何复杂的事情)。由于A和B非常简单并且非常接近相同,因此它们可以充当彼此的替代品。这有点像用凳子的腿代替桌腿:它们不一样,但足够接近它可能会起作用。但是,尝试用凳子的腿代替大象腿,事情不会那么顺利...... -
@Cornstalks 谢谢,这正是我正在寻找的答案。我仍然想知道为什么根本没有警告。
标签: c++ visual-c++ gcc polymorphism vtable