18

我很清楚class 和 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都没有警告过它。

4

6 回答 6

12

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

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

该标准区分了 using或定义class一个类,但在这里,谈到声明,没有这种区别——使用一个等同于任何其他。structunionclass-key

于 2011-02-01T19:04:53.510 回答
6

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

“理论上,理论和实践没有区别。实践中,有区别。”

于 2011-02-03T00:11:30.687 回答
4

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

于 2011-02-01T19:05:57.427 回答
3

在 C++ 中,结构是一个类。具体来说:

结构是使用 class-key 定义的类struct。(ISO/IEC FDIS 14882:1998(E) 9-4)

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

于 2011-02-01T18:43:28.023 回答
0

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

涂1

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

涂2

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

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

那么,至少有一些编译器(尤其是 MSVC++)会f在每个翻译单元中以不同的方式修改名称,因此fTU 1 中的定义不满足fTU 2 中的引用,并且您会收到链接错误。A.h当你有一个定义 classA并且需要引用 classes的标题时,这会在现实生活中出现B,但是它们的前向声明就足够了(所以它,很明智地,不包括等)——你最好使用相同的关键字对于实际定义所做的那些前向声明!CDB.h

于 2011-02-01T18:35:24.900 回答
0

MSVC10 抛出一个警告,警告页面指出将使用定义中给出的类型。

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

于 2011-02-01T18:43:48.923 回答