【问题标题】:Do I kill a kitten each time I use struct everywhere instead of class?每次我在任何地方都使用 struct 而不是 class 时,我会杀死一只小猫吗?
【发布时间】:2011-01-24 17:24:27
【问题描述】:

struct 默认为公开,class 默认为私有。

我们以 Ogre3D 为例;如果我用 struct 更改所有 class 出现,它会编译(我猜),并且引擎像以前一样工作。

如果我是对的,编译后的代码与以前完全相同,因为只有编译器会检查是否调用了私有/受保护的方法,而不是在运行时检查。

如果我还是对的,class 只是一个关键字,它只是让它可爱的眼睛并乞求“请封装你的数据:你会拯救一只小猫”,而私有/受保护范围仍然取决于用户.

我知道我听起来有点蹩脚或无关紧要的反叛(比如“C is KISS dude,不要走”

回到问题:在生成机器码时,标准对struct 和class 之间的这个小区别有何看法?为什么要添加一个关键字并试图用所谓的“OO 模型”给程序员留下深刻印象,而那时它完全没有被强制执行?受java影响吗?

【问题讨论】:

  • 实际上恰恰相反。每次使用“结构”就足够了的“类”关键字时,你就杀死了一只小猫。不,自从 C++ 出现以来就没有受到 Java 的影响。
  • C++ 不是严格意义上的 OO 语言,它是一种多范式语言,支持的不仅仅是 OO,因此它不会试图将 OO 概念强加给开发人员。如果他们愿意,开发人员可以使用 OO 风格。在此处查看 C++ 标记的信息条目stackoverflow.com/tags/c%2b%2b/info
  • stackoverflow.com/questions/4090794/…这个问题有更多答案。
  • “为什么要添加关键字” - 因为在 C++ 中它应该 是 class,但 struct 也是为了向后兼容 C。别担心,没有人试图给你留下深刻印象。实际上,编译器强制使用 struct 定义的任何类必须是 POD 可能很有用,但没有这样的运气。
  • "受 Java 影响吗?"哈哈哈。这很有趣!

标签: c++ class struct


【解决方案1】:

标准完全没有提到生成机器代码。

struct 被保留以简化旧版 C 代码的迁移。通常,C++ 程序员将其用于类似 POD 的结构。

【讨论】:

  • 正确。只有我几乎总是倾向于使用struct。如果我有private 或protected 成员并且除了编译器生成或继承的成员之外没有公共成员,我只使用class。这是因为我喜欢将我的私有成员放在底部,因为它们在类的界面中是最不有趣的。
【解决方案2】:

实际上,class 和 struct 都是在编译时检查的。唯一的区别是您未明确指定访问权限的成员的默认值是public(对于struct)还是private(对于class)。否则,它们会产生完全相同的对象。如果您明确指定所有访问控制,则可以使用其中任何一个,它们将是相同的。

【讨论】:

  • 无法保证它们生成相同的代码。特别是一个类的数据成员的布局保证只有在同一块内具有增加的内存地址。具有所有公共成员或所有私有成员的类将具有相同的布局,但符合标准的编译器可以决定将所有公共成员(按顺序)放在任何私有成员之前,无论它们在类定义中的什么位置。在这样的编译器中,将class 更改为struct 会破坏系统。
  • @David - 你确定吗?这些规则对于结构不是相同的吗?这对我来说是全新的。有参考吗?
  • 对于类或结构来说它们是相同的,唯一的区别是默认访问说明符,但不能保证:struct a { int x; protected: int y; }; 和class b { int x; protected: int y; }; 将具有相同的布局。引用将在第 9.2/12 节中“分配没有中间访问说明符的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址。非静态数据成员的分配顺序由访问说明符分隔的未指定 (11.1)。"
  • 其中 unspecified 意味着编译器可以决定顺序,并且允许符合标准的编译器将所有 public 成员一起移动到顶部(或底部)和所有 private 成员到另一端,这可能意味着最后一条注释中的两个结构可以在符合标准的编译器中产生不同的对象布局。
【解决方案3】:

struct 和class 之间的区别只是基和属性的默认访问级别,并且访问级别仅在编译时验证,因此您可能很想得到一些库编辑头文件并更改所有class 和struct 可以访问内部详细信息。

不要

如果您更改默认访问说明符,编译器不需要生成完全相同的代码。特别是这两个类可能具有或不具有相同的内存布局,具体取决于编译器:

struct a {
   int a;
private:
   int b:
};
class b {
   int a;
public:
   int b;
};

原因是标准要求所有成员属性在内存中布置在同一访问限定符内的递增位置。允许编译器(我不知道有什么,但由于这不是必需的,它可能会在下一个版本中更改)重新排序来自不同访问块的字段。编译器可以决定公共属性在前,而私有属性在对象末尾,这意味着两个类中字段a 和b 的位置将被交换。

【讨论】:

  • 我遇到了这个错误,但不是因为我将类切换到结构或反之亦然。我们实际上是在结构上标准化的。我所做的只是公开一个函数,然后忘记为我的一个模块升级 .lib。幸运的是,产生的条件是不可编译的,而不是导致奇怪的行为。
  • 我认为依赖特定的内存布局通常比在代码中用类替换结构或反之亦然更糟糕。
  • @wilhelmtell:我同意,但有时你没有注意到。特别是,对于给定的示例,如果您使用一些预编译的库(问题涉及 Ogre3D)并修改标头以访问私有成员,那么您的代码和库代码认为它们谈论的是同一个对象,但是当他们引用一个成员时,他们引用对象中的不同位(如果在新布局中不满足对齐要求,甚至可能是不同大小的对象。你依赖内存布局并不明显,但你这样做了每次编译。
  • 换句话说,它违反了 ODR。
【解决方案4】:

没有其他区别,但默认访问。实际上你甚至可以写这样的东西:

class X;

X* pX;

struct X {};

它必须编译。

【讨论】:

  • MSVC 会很合适。
【解决方案5】:

没有。 struct 和 class 之间的区别仅限于其成员和继承的默认可访问性。两者都是public 代表struct 和private 代表class

【讨论】:

    【解决方案6】:

    C++ 中结构体和类的唯一区别是类默认具有私有成员和基类。通常将class 更改为struct 应该不会影响生成的机器代码。

    【讨论】:

    • “默认基类”?你什么意思?结构可以有一个基,类也可以,但无论哪种情况,您都必须明确指定基。
    • @Seva Alekseyev:我的意思是类有“默认的私有基类”(默认访问适用于成员和基类)。
    【解决方案7】:

    不,它绝对没有受到 Java 的影响。检查时间线。 :)

    即使它只是控制默认可见性,它仍然非常有意义。这在某种程度上变成了让你说出你的意思的可用语义的问题。这个想法是,如果您使用struct,那么您可能是在一个旧范式中工作,其中公共可见性是通常会想到的唯一类型,如果您使用的是class,那么您就是以更多的 OO 术语思考,其中私有可见性受到更高的尊重——我不知道,这对我来说是有道理的,伙计。

    【讨论】:

      【解决方案8】:

      有些人试图使用 'struct' 关键字来表示各种事物。例如,有些人试图使用struct 来指定 POD 或仅作为数据类(只有公共成员变量且没有函数的类)。

      在我看来,这是一个严重的错误,我听到的所有理由都是有缺陷的。一方面,像struct 这样的关键字不足以表达他们试图使用它来记录的条件。由于关键字实际上并不意味着任何特定的人要么接受这一点,要么试图断言他们自己对它应该意味着什么的想法。关于struct 应该 在代码中的含义有太多不相容的意见,无法记录其中的任何一个。您希望尽可能清楚地记录诸如“此对象必须始终是 POD”之类的内容,而不是依赖于难以记住的晦涩的团队标准细节。所以,为了记录这样的事情,老实说,唯一足够的事情就是// This object must always be a POD。它清晰、简单,任何知道 POD 是什么的人都不会误解,而且定义明确。

      我听说过使用关键字class 而不是struct 的最佳论点是,您应该更喜欢私人访问而不是公共访问,只显示必要的内容。换句话说,“默认”类型的继承和访问公开应该是私有的,直到表明需要更多访问。我同意这个观点,但我不同意必须使用 struct 关键字来遵守这个原则。

      任何人的决定都是相当武断的。稍后可以断言该决定的原因,但我发现选择其中一个或另一个的人不容易说服。我从“类”切换到“结构”是因为我读了太多关于现代 C++ 的书和太多的 boost 代码;您很少会在其中看到“类”关键字。说实话,没关系;遵循您当时所在团队的标准。在我看来,添加一个本质上毫无意义的关键字是错误的。

      编辑:虽然,我不得不说我不喜欢使用class 的另一个原因是它意味着太多的东西,即使它也没有什么特别的意义。例如,您可以在模板参数规范中使用class 而不是typename。即使您使用class 关键字,您也可以传递任何类型,而不必传递任何类型的类(例如int)。我唯一喜欢使用 class 关键字的地方是它实际上确实意味着什么,而你实际上绝对必须这样做:指定模板模板参数。

      【讨论】:

        【解决方案9】:

        嗯,现在……如果你把这样的程序放到公共空间,比如 OSS,人们会向你扔石头;)

        struct 关键字是一种 C 遗产。是的,唯一的区别(据我所知)是关于受保护成员的默认行为。

        Bjarne Stroustrup 在“C++ 编程语言”中:

        根据定义,结构是一个类,其成员默认是公共的;那是

        结构体 { ...

        只是简写

        类 s { public: ...

        但 OO 模型远远不止是封装。它添加了继承和成员函数等内容。

        【讨论】:

        • 结构可以有继承和成员函数。 :)
        • 是的,我就是这么说的 :) 我刚才提到了这一点,因为 gokoon 的最后一句话:“为什么要添加一个关键字并尝试用所谓的“OO 模型”给程序员留下深刻印象,而它完全没有强制执行然后?”顺便提一下,OO 模型不仅仅是封装(但你是对的,现在我再次阅读它听起来有点像只有“类”才能实现它。
        【解决方案10】:

        struct 出于遗留原因而存在,仅此而已。使用 struct 而不是 class 时,您不会杀死小猫或任何东西,反之亦然 - 实际上,它们是相同的,只是关键字和默认值略有不同。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-01-10
          • 1970-01-01
          • 2010-10-28
          • 1970-01-01
          • 1970-01-01
          • 2021-06-03
          相关资源
          最近更新 更多