混合类和结构

发布于 2024-10-15 23:12:00 字数 907 浏览 8 评论 0原文

我很清楚类之间的区别和结构<​​/a>,但是我很难权威地说这是否定义良好:

// 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 甚至警告过这一点。

I'm well aware of the difference between class and struct, however I'm struggling to authoritatively say if this is well defined:

// 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;
}

If this is undefined behaviour can someone point me in the direction of an authoritative (i.e. chapter and verse from ISO) reference?

The compiler with problems handling this (Carbide 2.7) is relatively old and all the other compilers I've tried it on are perfectly happy with this, but clearly that doesn't prove anything.

My intuition was this ought to be undefined behaviour but I can't find anything to confirm this and I'm surprised that none of the GCC versions or Comeau so much as warned about it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

吃兔兔 2024-10-22 23:12:00

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

仅由类键标识符组成的声明;可以是对
当前作用域中的名称或将标识符向前声明为类名。它将类名引入到当前作用域中。

该标准在定义类时区分使用 classstructunion,但这里讨论的是声明,没有这样的区别——使用一个class-key与任何其他的都是等价的。

It looks to me like it's defined behavior. In particular, §9.1/2 says:

A declaration consisting solely of class-key identifier ; is either a redeclaration of the
name in the current scope or a forward declaration of the identifier as a class name. It introduces the class name into the current scope.

The standard distinguishes between using class, struct or union when defining a class, but here, talking about a declaration, no such distinction is made -- using one class-key is equivalent to any other.

奶茶白久 2024-10-22 23:12:00

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

“从理论上讲,理论和实践没有区别。在实践中,是有区别的。”

Technically the code is ok, according to the language standard. However, as at least one of the most popular compilers issues a warning for this, it doesn't work in practice.

"In theory, there is no difference between theory and practice. In pratice, there is."

哎呦我呸! 2024-10-22 23:12:00

来自 警告 C4099:类型名称第一次使用“class”,现在使用“struct”(MS VS 2k8) 似乎至少有一些编译器根据所使用的关键字进行不同的处理,所以最好不要依赖它,即使技术上允许(其中我找不到确认参考)。

From Warning C4099: type name first seen using 'class' now seen using 'struct' (MS VS 2k8) it appears that at least some compilers mangle differently depending on keyword used, so best not to rely on it even if it's technically allowed (of which I can't find a confirming reference).

旧情勿念 2024-10-22 23:12:00

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

结构体是一个类,定义为
类键struct。 (ISO/IEC FDIS
14882:1998(E)9-4)

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

In C++, a struct is a class. Specifically:

A structure is a class defined with
the class-key struct. (ISO/IEC FDIS
14882:1998(E) 9-4)

This implies that your class, which was not defined with struct, is definitely not a struct. Therefore, your forward declaration with the struct class-key is erroneous. I'm not aware of any part of the specification that allows a forward declaration to use a class-key that is clearly wrong. I'm sure that the lenient compilers in question treat structs and classes equally and are glossing over the incorrect declaration. An error may not be required from the compiler in this scenario, but neither should it be unexpected.

以酷 2024-10-22 23:12:00

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

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 的定义不满足 TU 2 中对 f 的引用,并且您会收到链接错误。在现实生活中,当您有一个定义类 A 的标头 Ah 并需要引用类 BC< 时,就会出现这种情况/code> 和 D 但它们的前向声明就足够了(因此,非常明智的是,包括 Bh 等)——你最好对那些实际定义所做的前向声明使用相同的关键字!

I have no idea whether or not this is undefined (or any of the other categories of not-strictly-conforming) per the C standard, but I do know that if you have two translation units that don't agree on whether a type 'foo' is declared as a 'class' or a 'struct', like so:

TU 1

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

TU 2

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

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

then, at least some compilers (notably MSVC++) will mangle the name of f differently in each translation unit, so the definition of f in TU 1 does not satisfy the reference to f in TU 2 and you get a link error. This comes up in real life when you have a header A.h that defines class A and needs to refer to classes B, C, and D but a forward declaration of them suffices (so it, quite sensibly, does not include B.h etc) -- you better use the same keyword for those forward declarations that the actual definitions do!

孤独患者 2024-10-22 23:12:00

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

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

MSVC10 throws a warning, and the warning page states that the type given in the definition will be used.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文