471

已经在 C#/.Net 的上下文中提出了这个问题。

现在我想了解 C++ 中结构和类之间的区别。请讨论技术差异以及在 OO 设计中选择其中一种的原因。

我将从一个明显的区别开始:

  • 如果不指定public:or private:,则结构的成员默认是公共的;默认情况下,类的成员是私有的。

我确信在 C++ 规范的晦涩角落中还可以找到其他差异。

4

30 回答 30

480

您忘记了类和结构之间棘手的第二个区别。

引用标准(C++98 到 C++11 中的第 11.2.2 节):

在基类没有访问说明符的情况下 ,当派生类声明为 struct时假定为 public,而当声明为 class 时假定为 private 。

为了完整起见,类和结构之间更广为人知的区别在 (11.2) 中定义:

默认情况下,使用关键字 class 定义的类的成员私有的。默认情况下,使用关键字structunion定义的类的成员 是公共的。

附加区别:关键字class可以用来声明模板参数,而struct关键字不能这样使用。

于 2009-06-16T06:19:01.103 回答
167

引用C++ FAQ

[7.8]关键字struct和class有什么区别?

结构的成员和基类默认是公共的,而在类中,它们默认是私有的。注意:您应该明确地使您的基类公开、私有或受保护,而不是依赖默认值。

结构和类在其他方面在功能上是等价的。

好的,足够干净的技术谈话了。从情感上讲,大多数开发人员在类和结构之间做出了强烈的区分。结构感觉就像是一堆开放的位,封装或功能的方式很少。一个类感觉就像是一个活生生的、负责任的社会成员,具有智能服务、强大的封装屏障和定义明确的接口。由于这是大多数人已经拥有的含义,因此如果您的类具有很少的方法并且具有公共数据(这样的事情确实存在于设计良好的系统中!),您可能应该使用 struct 关键字,否则您可能应该使用该类关键词。

于 2008-09-18T14:18:44.153 回答
130

值得记住 C++ 的起源以及与 C 的兼容性。

C 有结构,没有封装的概念,所以一切都是公开的。

在采用面向对象的方法时,默认情况下公开通常被认为是一个坏主意,因此在制作一种原生有利于 OOP 的 C 形式时(您可以在 C 中执行 OO,但它对您没有帮助),这是C++ 中的想法(最初是“C With Classes”),默认情况下将成员设为私有是有意义的。

另一方面,如果 Stroustrup 更改了 的语义struct,使其成员默认为私有,则会破坏兼容性(不再像标准分歧那样经常如此,但所有有效的 C 程序也是有效的 C++ 程序,这对让 C++ 站稳脚跟有很大的影响)。

所以引入了一个新的关键字,class它与结构完全一样,但默认情况下是私有的。

如果 C++ 是从零开始,没有历史,那么它可能只有一个这样的关键字。它也可能不会产生它所产生的影响。

一般来说,人们在做类似 C 中如何使用结构的事情时会倾向于使用结构。公共成员,没有构造函数(只要它不在联合中,你可以在结构中拥有构造函数,就像类一样,但人们倾向于不这样做),没有虚拟方法等。因为语言与通信一样多人们阅读代码来指导机器(否则我们会坚持使用汇编和原始 VM 操作码),坚持下去是个好主意。

于 2010-08-07T23:17:38.190 回答
35

类的成员默认是私有的。结构的成员默认是公开的。除此之外没有其他区别。另请参阅此问题

于 2008-09-18T14:12:32.140 回答
31

根据C++ 编程语言中的 Stroustrup :

您使用哪种风格取决于环境和品味。我通常更喜欢struct用于所有数据都公开的类。我认为这样的类“不是很合适的类型,只是数据结构”。

功能上,除了public/private没有区别

于 2008-09-18T14:15:12.990 回答
13
  1. 类的成员默认是私有的,结构的成员默认是公有的

例如程序 1 编译失败,程序 2 工作正常。

// Program 1
#include <stdio.h>
 
class Test {
    int x; // x is private
};

int main()
{
  Test t;
  t.x = 20; // compiler error because x is private
  getchar();
  return 0;
}
// Program 2
#include <stdio.h>
 
struct Test {
    int x; // x is public
};

int main()
{
  Test t;
  t.x = 20; // works fine because x is public
  getchar();
  return 0;
}
  1. 从类/结构派生结构时,基类/结构的默认访问说明符是 public。并且在派生类时,默认访问说明符是 private

例如程序 3 编译失败,程序 4 工作正常。

// Program 3
#include <stdio.h>
 
class Base {
public:
    int x;
};
 
class Derived : Base { }; // is equivalent to class Derived : private Base {}
 
int main()
{
  Derived d;
  d.x = 20; // compiler error because inheritance is private
  getchar();
  return 0;
}
// Program 4
#include <stdio.h>
 
class Base {
public:
    int x;
};
 
struct Derived : Base { }; // is equivalent to struct Derived : public Base {}
 
int main()
{
  Derived d;
  d.x = 20; // works fine because inheritance is public
  getchar();
  return 0;
}
于 2015-07-24T05:44:13.843 回答
11

STRUCT 是一种抽象数据类型,它根据结构规范划分给定的内存块。结构在文件序列化/反序列化中特别有用,因为结构通常可以逐字写入文件。(即获取指向结构的指针,使用 SIZE 宏计算要复制的字节数,然后将数据移入或移出结构。)

类是一种不同类型的抽象数据类型,它试图确保信息隐藏。在内部,可以有各种机制、方法、临时变量、状态变量。等等,它们都用于为希望使用该类的任何代码提供一致的 API。

实际上,结构是关于数据的,类是关于代码的。

但是,您确实需要了解这些仅仅是抽象。完全有可能创建看起来很像类的结构和看起来很像结构的类。事实上,最早的 C++ 编译器只是将 C++ 代码翻译成 C 的预编译器。因此,这些抽象对逻辑思维是有益的,而不一定是计算机本身的资产。

除了每个都是不同类型的抽象之外,类还为 C 代码命名难题提供了解决方案。由于不能有多个同名函数公开,因此开发人员过去常常遵循 _() 模式。例如 mathlibextreme_max()。通过将 API 分组到类中,可以将类似的函数(这里我们称之为“方法”)组合在一起,并防止在其他类中命名方法。这允许程序员更好地组织他的代码并增加代码重用。理论上,至少。

于 2008-09-18T14:23:30.927 回答
8

唯一的另一个区别是类和结构的默认继承,不出所料,它们分别是私有的和公共的。

于 2008-09-18T14:15:19.043 回答
6

class和之间struct的区别是关键字之间的区别,而不是数据类型之间的区别。这两个

struct foo : foo_base { int x;};
class bar : bar_base { int x; };

两者都定义了一个类类型。此上下文中关键字的不同之处在于默认访问权限不同:

  • foo::x是公开的并且foo_base是公开继承的
  • bar::x是私有的并且bar_base是私有继承的
于 2019-06-19T20:35:59.393 回答
5
  1. 结构的成员默认是公共的,类的成员默认是私有的。
  2. Structure 从另一个结构或类的默认继承是公共的。从另一个结构或类的类的默认继承是私有的。
class A{    
public:    
    int i;      
};

class A2:A{    
};

struct A3:A{    
};


struct abc{    
    int i;
};

struct abc2:abc{    
};

class abc3:abc{
};


int _tmain(int argc, _TCHAR* argv[])
{    
    abc2 objabc;
    objabc.i = 10;

    A3 ob;
    ob.i = 10;

    //A2 obja; //privately inherited
    //obja.i = 10;

    //abc3 obss;
    //obss.i = 10;
}

这是在VS2005上。

于 2008-09-19T10:12:11.273 回答
4

不在规范中,没有。主要区别在于程序员在 2 年内阅读您的代码时的期望。结构通常被假定为 POD。当您为定义对象以外的目的定义类型时,结构也用于模板元编程。

于 2008-09-18T14:15:11.307 回答
4

需要注意的另一件事是,如果您更新了具有使用类的结构的旧版应用程序,您可能会遇到以下问题:

旧代码有结构,代码被清理,这些变成了类。然后将一两个虚函数添加到新更新的类中。

当虚函数在类中时,编译器将在内部添加指向类数据的额外指针以指向函数。

这将如何破坏旧的遗留代码是,如果在旧代码中的某个地方使用 memfill 清除结构以将其全部清除为零,这也会破坏额外的指针数据。

于 2008-09-18T15:31:53.290 回答
4

另一个主要区别是在模板方面。据我所知,您可以在定义模板而不是结构时使用类。

template<class T> // OK
template<struct T> // ERROR, struct not allowed here
于 2011-11-12T11:21:53.650 回答
4
  1. 默认情况下,使用关键字定义的类的成员class。默认情况下private,使用关键字struct(or union)定义的类的成员。public

  2. 如果基类没有访问说明符,public则在声明派生类时假定,并在声明structprivate时假定class

  3. 您可以声明一个enum class但不能声明一个enum struct.

  4. 您可以使用template<class T>但不能使用template<struct T>.

另请注意,C++ 标准允许您将类型前向声明为 a struct,然后class在声明类型时使用,反之亦然。此外,std::is_class<Y>::value对于trueY 是 astruct和 a class,但是false对于 a enum class

于 2018-12-19T14:00:23.890 回答
2

这是一个很好的解释:http ://carcino.gen.nz/tech/cpp/struct_vs_class.php

因此,再一次:在 C++ 中,结构与类相同,只是结构的成员默认具有公共可见性,但类的成员默认具有私有可见性。

于 2008-09-18T14:13:29.017 回答
2

这只是一个约定。可以创建结构来保存简单数据,但后来随着成员函数和构造函数的添加而演变。另一方面,看到除 public 之外的任何东西是不寻常的:在结构中访问。

于 2008-09-18T14:17:42.300 回答
2

ISO IEC 14882-2003

9班

§3

结构是使用class-key struct定义的类;它的成员和基类(第 10 条)默认是公共的(第 11 条)。

于 2010-04-18T09:18:14.243 回答
1

其他答案提到了私有/公共默认值,(但请注意,结构是类是结构;它们不是两个不同的项目,只是定义同一项目的两种方式)。

值得注意的是(特别是因为提问者可能正在使用 MSVC++,因为他提到了“非托管”C++)是 Visual C++ 在某些情况下会抱怨,如果一个类是用声明class然后定义的struct(或者可能反过来),尽管标准说这是完全合法的。

于 2011-08-04T14:25:00.830 回答
1
  • . 在类中,默认情况下所有成员都是私有的,但在结构中,默认情况下成员是公共的。

    1. 结构没有构造函数和析构函数之类的术语,但是如果您不提供,则类编译器会创建默认值。

    2. Sizeof 空结构是 0 Bytes 或者 Sizeof 空类是 1 Byte 结构默认访问类型是 public。通常应该使用结构来对数据进行分组。

    类默认访问类型是私有的,继承的默认模式是私有的。应该使用一个类来对数据和对该数据进行操作的方法进行分组。

    简而言之,约定是当目的是对数据进行分组时使用结构,而当我们需要数据抽象和可能继承时使用类。

    在 C++ 中,结构和类是按值传递的,除非显式取消引用。在其他语言中,类和结构可能具有不同的语义——即。对象(类的实例)可以通过引用传递,结构可以通过值传递。注意:有与此问题相关的评论。请参阅讨论页添加到对话。

于 2012-07-10T19:07:09.190 回答
1

虽然其他答案暗示了这一点,但并未明确提及 - 结构与 C 兼容,具体取决于使用情况;类不是。

这意味着如果您正在编写一个希望与 C 兼容的标头,那么除了 struct (在 C 世界中不能有函数;但可以有函数指针)之外,您别无选择。

于 2016-09-29T11:38:01.740 回答
-1

您可以考虑将其作为何时使用 struct 或 class 的指南,https://msdn.microsoft.com/en-us/library/ms229017%28v=vs.110%29.aspx

√ 如果类型的实例很小且通常短暂存在或通常嵌入在其他对象中,请考虑定义结构而不是类。

X 避免定义结构,除非该类型具有以下所有特征:

它在逻辑上表示单个值,类似于原始类型(int、double 等)。

它的实例大小小于 16 个字节。

它是不可变的。

它不必经常装箱。

于 2015-05-01T12:30:43.610 回答
-2

类仅在软件工程的上下文中才有意义。在数据结构和算法的上下文中,类和结构没有那么不同。没有任何规则限制必须引用该类的成员。

当开发有大量没有课程的人的大型项目时,您最终可能会得到复杂的耦合代码,因为每个人都使用他们想要的任何函数和数据。类提供权限控制和固有功能以增强解耦和重用代码。

如果您阅读了一些软件工程原理,您会发现大多数标准如果不上课就无法轻松实现。例如: http ://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29

顺便说一句,当结构分配大量内存并包含多个变量时,值类型变量表示值嵌入在分配结构的位置。相反,引用类型变量的值是外部的,并且由一个指针引用,该指针也嵌入在分配结构的位置。

于 2015-03-16T16:49:09.007 回答
-3

C++中structclass关键字的区别在于,当特定复合数据类型没有特定说明符时,默认structunion是public关键字,只考虑数据隐藏,class是private关键字,考虑隐藏程序代码或数据。总是有些程序员为了代码而使用结构来存储数据和。有关更多信息,请联系其他来源。

于 2013-04-15T13:57:45.987 回答
-3

在所有这些因素中,可以得出结论,概念类非常适合表示现实世界的对象,而不是“结构”。很大程度上是因为类中使用的 OOP 概念在解释现实世界场景时非常实用,因此更容易将它们与现实结合起来。例如,结构的默认继承是公共的,但如果我们将此规则应用于现实世界,那就太荒谬了。但是在一个类中,默认继承是私有的,这更现实。

无论如何,我需要证明的是类是一个更广泛的、现实世界适用的概念,而结构是一个内部组织很差的原始概念(尽管结构遵循 OOP 概念,但它们的含义很差)

于 2013-08-27T01:22:29.987 回答
-3

oops 中结构体和类关键字的主要区别在于,结构体中不存在公共和私有成员声明。数据成员和成员函数可以定义为公共、私有和受保护的。

于 2014-01-28T19:50:07.233 回答
-4

**更新:**请忽略此回复。我没有考虑结构体的值未初始化而恰好为0的可能性。结构体和类之间没有初始化差异。


我看到与默认初始化有关的结构和类之间的另一个不同之处。

struct Foo {
    int a;
};

class Bar {
    int a;
};

class Tester {
    Foo m_Foo = Foo();
    Bar m_Bar = Bar();

public:
    Tester() {}
};

int main() {
    auto myTester = Tester();
}

运行该代码并检查 myTester。您会发现对于 m_Foo,结构体 m_Foo.a 已初始化为 0,但对于 m_Bar,类 m_Bar.a 未初始化。因此,默认构造函数对结构和类的作用似乎确实有所不同。我在 Visual Studio 中看到了这一点。

于 2015-07-15T18:21:35.397 回答
-4

struct 和 class 的主要区别在于,struct 中只能声明不同数据类型的数据变量,而 class 中可以声明数据变量、成员函数,从而可以通过函数来​​操作数据变量。

-> 我在类 vs 结构中发现的另一个方便的事情是,在程序中实现文件时,如果你想在每组新操作上一次又一次地对结构进行一些操作,你需要创建一个单独的函数,你需要从文件中读取结构的对象后传递它,以便对其进行一些操作。在课堂上,如果您创建一个函数,该函数每次都对所需的数据进行一些操作..它很容易,您只需从文件中读取对象并调用该函数..

但这取决于程序员他/她认为哪种方式合适......根据我的说法,我每次都喜欢上课,因为它支持 OOP,这就是它在几乎所有语言中实现的原因以及它所有时间编程的美妙特性;- )

是的,我忘了提到的最难忘的区别是,类支持数据隐藏,还支持在内置数据类型上执行的操作,而 struct 不支持!

于 2017-06-09T13:14:36.580 回答
-5

我发现了另一个不同之处。如果您没有在类中定义构造函数,编译器将定义一个。但是在结构中,如果你没有定义构造函数,编译器也不会定义构造函数。所以在某些我们真的不需要构造函数的情况下,struct 是更好的选择(性能提示)。对不起我的英语不好。

于 2011-08-04T13:28:15.140 回答
-5

类是引用类型,结构是值类型。
当我说类是引用类型时,
基本上它们将包含实例变量的地址。

例如:

Class MyClass
{
    Public Int DataMember;  //By default, accessibility of class data members 
                            //will be private. So I am making it as Public which 
                            //can be accessed outside of the class.
}

在 main 方法中,
我可以使用 new 运算符创建此类的实例,该运算符为此类分配内存
并将其基地址存储到 MyClass 类型变量(_myClassObject2)中。

Static Public void Main (string[] arg)
{
    MyClass _myClassObject1 = new MyClass();
    _myClassObject1.DataMember = 10;

    MyClass _myClassObject2 = _myClassObject1;
    _myClassObject2.DataMember=20;
}

在上述程序中,MyClass _myClassObject2 = _myClassObject1; 指令表明 MyClass 类型的两个变量

  1. 我的类对象1
  2. 我的类对象2

并将指向相同的内存位置。
它基本上将相同的内存位置分配给另一个相同类型的变量。

因此,如果我们对任何一个对象类型 MyClass 所做的任何更改都会对另一个对象产生影响,
因为两者都指向相同的内存位置。

“_myClassObject1.DataMember = 10;” 在这一行,对象的两个数据成员都将包含值 10。
“_myClassObject2.DataMember = 20;” 在这一行,对象的数据成员都将包含 20 的值。
最终,我们通过指针访问对象的数据成员。

与类不同,结构是值类型。例如:

Structure MyStructure
{
    Public Int DataMember;  //By default, accessibility of Structure data 
                            //members will be private. So I am making it as 
                            //Public which can be accessed out side of the structure.
}

Static Public void Main (string[] arg)
{
    MyStructure _myStructObject1 = new MyStructure();
    _myStructObject1.DataMember = 10;

    MyStructure _myStructObject2 = _myStructObject1;
    _myStructObject2.DataMember = 20;
}

在上述程序中,
使用 new 运算符实例化 MyStructure 类型的对象
并将地址存储到 MyStructure 类型的 _myStructObject 变量中,并
使用“_myStructObject1.DataMember = 10”将值 10 分配给结构的数据成员。

在下一行中,
我声明了另一个 MyStructure 类型的变量 _myStructObject2 并将 _myStructObject1 分配给它。
此处 .NET C# 编译器创建 _myStructureObject1 对象的另一个副本,
并将该内存位置分配给 MyStructure 变量 _myStructObject2。

因此,无论我们对 _myStructObject1 所做的任何更改都不会对另一个 MyStructObject 类型的变量 _myStructObject2 产生影响。
这就是为什么我们说结构是值类型。

所以类的直接基类是对象,结构的直接基类是继承自 Object 的 ValueType。
类将支持继承,而结构则不支持。

我们怎么说呢?
这背后的原因是什么?
答案是类。

它可以是抽象的、密封的、静态的和部分的,不能是私有的、受保护的和受保护的内部的。

于 2013-09-25T10:54:45.823 回答
-8

结构和类之间有3个基本区别

1St-内存是为堆栈内存中的结构保留的(接近编程语言),堆栈内存中的类是否保留仅用于引用和实际内存保留在堆内存中。

2Nd - 默认情况下,结构视为公共,无论类视为私有。

3Rd-不能在结构中重用代码,但在类中我们可以多次重用相同的代码,称为inhertence

于 2014-12-05T14:45:45.223 回答