假设我们遇到这样的情况:
base.h:
class Base { };
derived.h:
#include "base.h"
class Derived : public Base { };
extern Derived *variable;
derived.cpp:
#include "derived.h"
Derived *variable;
在otherwise.cpp中将variable
声明为Base
的指针是否正确?
class Base;
extern Base *variable;
C ++ Builder链接器没有抱怨,一切似乎都有效。根据标准,这是安全和正确的,还是variable
的每个声明都属于同一类型?
答案 0 :(得分:2)
不行。如果名称variable
应该引用同一个实体(因为它是extern
),那么它必须具有相同的类型。否则,您将违反ODR(一个定义规则)。
答案 1 :(得分:2)
以下是一些可能出错的方法(除了未定义的行为,这意味着您甚至不应该依赖其中一种行为):
假设在某些时候Derived
更改为
class Derived : public Something, public Base {};
其中Something
不为空,那么在大多数ABI中,当Derived*
转换为Base*
时,Base*
会更改其值。但是,全局变量的别名会绕过此调整,从而使Base
不会指向OtherDerived
。
编译器实际上可能通过其他方式检测到您的ODR违规,并且只是出错。
Base
类型的对象(也来自Derived
,而不是variable
)分配给Derived*
,会发生什么?程序中将其视为Derived
的部分期望它指向OtherDerived
,但它确实指向foo
。你可以在这样的代码中看到最迷人的效果。您可以进行设置,以便在Derived
调用foo2
版本时调用虚拟函数OtherDerived
调用{{1}}版本。可能性无穷无尽。答案 2 :(得分:1)
当然不行。
在某些情况下会产生歧义:
// Example Function:
void do_stuff(Base* b);
// Code
do_stuff(variable); // You could mean Derived* or Base*.
// You would write the same thing, but mean
// 2 different things.