2

假设我们有这样的情况:

基地.h:

class Base { };

派生的.h:

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

派生的.cpp:

#include "derived.h"
Derived *variable; 

variable声明为 else.cpp 中的指针是否正确Base

class Base;
extern Base *variable;

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

4

3 回答 3

2

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

于 2013-06-18T13:20:01.267 回答
2

这里有几种可能出错的方法(除了未定义的行为,这意味着您甚至不应该依赖其中一种发生):

  • 编译器可能会将类型作为变量修饰的一部分。显然 C++Builder 没有,但我很确定 MSVC 有。如果是这样,您会收到链接器错误。
  • 假设在某个时候Derived更改为

    class Derived : public Something, public Base {};

    whereSomething不为空,然后在大多数 ABI 中, a 在Derived*转换为 a 时会更改其值Base*。但是,全局变量的别名绕过了这种调整,留下了Base*不指向 a 的 a Base

  • 编译器实际上可能会通过其他方式检测到您的 ODR 违规,然后就会出错。

  • 如果你将一个类型的对象OtherDerived(它也派生自Base,但不是Derived)分配给你的variable? 将它视为 a 的程序部分Derived*期望它指向 a Derived,但它实际上指向 a OtherDerived。您可以在这样的代码中看到最迷人的效果。您可以对其进行设置,以便在调用版本时调用虚函数foo调用版本。可能性是无止境。Derivedfoo2OtherDerived
于 2013-06-18T13:37:09.413 回答
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.
于 2013-06-18T13:32:44.273 回答