2013-06-18 24 views
1

假设我们有这样的情况:声明为外部变量如基类和派生类指针

base.h:

class Base { }; 

derived.h:

#include "base.h" 
class Derived : public Base { }; 
extern Derived *variable; 

derived.cpp :

#include "derived.h" 
Derived *variable; 

是否正确t宣布variable作为指向Base在别处cpp?

class Base; 
extern Base *variable; 

C++ Builder链接器没有抱怨,一切似乎工作。根据标准,这是安全和正确的,还是每个variable的声明都应该是同一类型的?

回答

2

下面的几个方面,这可以去错了(除了是不确定的行为,这意味着你应该甚至不应该依赖于那些发生的一个):

  • 编译器可能使类型变成部分变形。显然C + + Builder不,但我很确定MSVC确实。如果是这样,你会得到链接器错误。
  • 假设在某个时刻Derived改为

    class Derived : public Something, public Base {};

    其中Something不为空,那么在大多数的ABI,当它转换为Base*一个Derived*改变其价值。但是,全局变量的别名会绕过此调整,使您留下的Base*不会指向Base

  • 编译器可能会实际上是通过一些其他手段检测到您的ODR违规,只是错误的。

  • 如果分配OtherDerived类型的对象会发生什么(这也得益于Base派生,而不是Derived)你variable?程序中看到它为Derived*的部分指望它指向Derived,但它确实指向OtherDerived。您可以在此类代码中看到最迷人的效果。您可以将其设置为使调用虚拟功能foo调用Derived版本,而foo2调用OtherDerived版本。可能性是无止境。
2

这是不正确的。如果名称variable应该引用同一个实体(它是,因为它是extern),那么它必须具有相同的类型。否则,您将违反ODR(一个定义规则)。

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. 
相关问题