混合类和结构

时间:2011-02-01 18:23:31

标签: c++ class struct undefined-behavior

我很清楚difference between class and struct,但是我很难权威地说出这个定义是否明确:

// declare foo (struct)
struct foo;

// define foo (class)
class foo {
};

// instance of foo, claiming to be a struct again! Well defined?
struct foo bar;

// mixing class and struct like this upsets at least one compiler (names are mangled differently)
const foo& test() {
   return bar;
}

int main() {
   test();
   return 0;
}

如果这是未定义的行为,有人可以指向权威(即ISO的章节和经文)参考吗?

处理此问题的编译器(Carbide 2.7)相对较旧,我尝试过的所有其他编译器对此非常满意,但显然没有任何证据。

我的直觉是这应该是未定义的行为,但我无法找到任何证实这一点,我很惊讶没有GCC版本或Comeau如此警告它。

6 个答案:

答案 0 :(得分:11)

在我看来它是定义的行为。特别是,§9.1/ 2说:

  

仅由class-key identifier ;组成的声明要么重新声明   当前范围中的名称或标识符的前向声明作为类名。它将类名引入当前范围。

标准区分了在定义类时使用classstructunion,但在这里,谈论声明,没有做出这样的区分 - 使用一个class-key等同于任何其他。

答案 1 :(得分:5)

从技术上讲,根据语言标准,代码是可以的。但是,由于至少有一个最受欢迎的编译器会对此发出警告,因此在实践中不起作用。

“从理论上讲,理论与实践之间没有区别。在实践中,有。”

答案 2 :(得分:4)

Warning C4099: type name first seen using 'class' now seen using 'struct' (MS VS 2k8)看来,至少有些编译器会根据所使用的关键字进行不同的编辑,因此即使技术上允许,也最好不要依赖它(我无法找到确认参考)。

答案 3 :(得分:2)

在C ++中,struct是一个类。具体做法是:

  

结构是一个定义的类   类密钥struct。 (ISO / IEC FDIS   14882:1998(E)9-4)

这意味着您的类已定义 struct,绝对不是结构。因此,使用struct class-key的前向声明是错误的。我不知道规范的任何部分允许前向声明使用明显错误的类键。我确信有问题的宽松编译器能够平等地处理结构和类,并且正在掩盖不正确的声明。在这种情况下,编译器可能不需要出错,但也不应该是意外的。

答案 4 :(得分:0)

根据C标准,我不知道这是否是未定义的(或任何其他非严格符合的类别),但我知道如果你有两个翻译单位不同意是否类型'foo'被声明为'class'或'struct',如下所示:

TU 1

struct foo;
void f(foo&) { ... }

TU 2

class foo { ... };
void f(foo&);

void g()
{
  foo x;
  f(x);
}

然后,至少一些编译器(特别是MSVC ++)会在每个翻译单元中以不同方式破坏f的名称,因此TU 1中f的定义不满足{{1}的引用在TU 2中你得到一个链接错误。如果您有一个定义类f的标题A.h并且需要引用类ABC,那么现实生活就会出现这种情况。它们的前向声明就足够了(所以它非常明智地包括D等) - 你最好使用与实际定义相同的前向声明的关键字!

答案 5 :(得分:0)

MSVC10会发出警告,警告页面会指出将使用定义中给出的类型。

http://msdn.microsoft.com/en-us/library/695x5bes.aspx