什么时候应该在C++中使用类和结构?

在什么情况下,在C++中使用structclass更好?

550295 次浏览

C++中classstruct的区别是:

  • struct成员和基类/结构默认为public
  • class成员和基类/结构默认为private

类和结构都可以具有publicprotectedprivate成员的混合物,可以使用继承,并且可以具有成员函数。

我向您推荐:

  • 对于没有任何类特征的普通旧数据结构使用struct
  • 当您使用privateprotected成员、非默认构造函数和运算符等功能时,请使用class

C++,结构体和类之间真的没有太大区别。主要的功能区别是结构体的成员默认是公共的,而它们在类中默认是私有的。否则,就语言而言,它们是等价的。

也就是说,我倾向于在C++中使用结构,就像我在C#中所做的那样,类似于Brian所说的。结构是简单的数据容器,而类用于除了保存数据之外还需要对数据进行操作的对象。

它们几乎是一样的。多亏了C++的魔力,结构可以像类一样保存函数、使用继承、使用“new”创建等等

唯一的功能区别是类以私有访问权限开头,而结构以公共访问权限开头。这是与C保持向后兼容。

在实践中,我总是使用结构作为数据持有者,使用类作为对象。

结构对我有帮助的一个地方是当我有一个系统从另一个系统接收固定格式的消息(比如串行端口)时。您可以将字节流转换为定义您的字段的结构,然后轻松访问字段。

typedef struct{int messageId;int messageCounter;int messageData;} tMessageType;
void processMessage(unsigned char *rawMessage){tMessageType *messageFields = (tMessageType *)rawMessage;printf("MessageId is %d\n", messageFields->messageId);}

显然,这与您在C中会做的事情相同,但我发现必须将消息解码为类的开销通常是不值得的。

回答我自己的问题(无耻地),如前所述,访问权限是C++中它们之间的唯一区别。

我倾向于只使用结构来存储数据。如果它可以更容易地处理数据,我会允许它获得一些辅助函数。然而,一旦数据需要流控制(即维护或保护内部状态的getter/setter)或开始获取任何主要功能(基本上更像对象),它将被“升级”到一个类来更好地传达意图。

当您提供具有C++实现的C兼容接口时,结构(POD,更一般地说)很方便,因为它们可以跨语言边界和链接器格式移植。

如果这不是你关心的问题,那么我想使用“struct”而不是“class”是一个很好的意图传达者(正如@ZeroSignal上面所说)。结构也有更可预测的复制语义学,所以它们对你打算写入外部媒体或通过网络发送的数据很有用。

结构对于各种元编程任务也很方便,比如只公开一堆依赖的typedef的特征模板:

template <typename T> struct type_traits {typedef T type;typedef T::iterator_type iterator_type;...};

…但这实际上只是利用struct的默认保护级别是公共的…

我从不在C++中使用“struct”。

我无法想象当你想要私有成员时会使用结构的场景,除非你故意试图混淆。

似乎使用结构更多的是一种语法指示数据将如何使用,但我宁愿创建一个类,并尝试在类的名称中或通过注释明确表示。

例如。

class PublicInputData {//data members};

我唯一一次使用结构而不是类是在函数调用中使用仿函数之前声明它,并且为了清晰起见想要最小化语法。

struct Compare { bool operator() { ... } };std::sort(collection.begin(), collection.end(), Compare());

它们是相同的,具有不同的默认值(默认为class的私有,默认为struct的公共),因此理论上它们是完全可互换的。

所以,如果我只是想打包一些信息来移动,我会使用一个struct,即使我在那里放了一些方法(但不是很多)。如果它是一个基本上不透明的东西,主要用途是通过方法,而不是直接到数据成员,我使用一个完整的类。

结构默认具有公共访问权限,类默认具有私有访问权限。

就我个人而言,我使用结构作为数据传输对象或值对象。当这样使用时,我将所有成员声明为const以防止被其他代码修改。

正如其他人所指出的,实际上只有两种实际的语言差异:

  • struct默认为公共访问,class默认为私有访问。
  • 当继承时,struct默认为public继承,class默认为private继承(具有讽刺意味的是,与C++中的许多事情一样,默认是向后的:public继承是迄今为止更常见的选择,但人们很少声明struct只是为了节省键入“public”关键字。

但实践中真正的区别在于声明了构造函数/析构函数的class/struct和没有声明构造函数/析构函数的class/struct之间。“普通旧数据”POD类型有某些保证,一旦你接管了类的构造,这些保证就不再适用。为了保持这种区别清晰,许多人故意只对POD类型使用struct,如果他们要添加任何方法,请使用classes。下面两个片段之间的区别在其他方面毫无意义:

class X{public:
// ...};
struct X{// ...};

(顺便说一句,这里有一个关于“POD类型”实际上意味着什么的很好的解释:C++中的POD类型有哪些?

C++FAQ Lite

默认情况下,结构的成员和基类是公共的,而在类中,它们默认为私有。注意:您应该将基类显式设置为公共、私有或受保护,而不是依赖默认值。

struct和class在功能上是等价的。

好了,我说的够多了。从情感上讲,大多数开发人员对类和结构有着很强的区分。结构感觉就像一堆开放的比特,几乎没有封装或功能。类感觉就像是社会中活生生的、负责任的一员,拥有智能服务、强大的封装屏障和定义良好的接口。由于这是大多数人已经有的内涵,如果你有一个方法很少且有公共数据的类(在设计良好的系统中确实存在这样的东西!),你可能应该使用struct关键字,但否则你可能应该使用class关键字。

我认为结构是一种数据结构(就像一个多数据类型的信息数组),类是为代码打包而集成的(就像子程序和函数的集合)。

问题:(

仅当我需要保存一些数据而不与之关联的任何成员函数(对成员数据进行操作)并直接访问数据变量时,我才使用struct。

例如:从文件和套接字流等读取/写入数据。在函数参数太多且函数语法看起来太长的结构中传递函数参数。

从技术上讲,类和结构之间没有太大的区别,除了默认的可访问性。更重要的是,它取决于你如何使用它的编程风格。

从技术上讲,两者在C++上是相同的-例如,结构可能具有重载运算符等。

但是:

当我想同时传递多种类型的信息时,我使用结构当我处理“函数”对象时,我使用类。

希望有帮助。

#include <string>#include <map>using namespace std;
struct student{int age;string name;map<string, int> grades};
class ClassRoom{typedef map<string, student> student_map;public :student getStudentByName(string name) const{ student_map::const_iterator m_it = students.find(name); return m_it->second; }private :student_map students;};

例如,我在这里的get…()方法中返回一个struct学生-享受。

正如每个人所说,唯一真正的区别是默认访问。但当我不想用简单的数据类进行任何形式的封装时,我特别使用struct,即使我实现了一些辅助方法。例如,当我需要这样的东西时:

struct myvec {int x;int y;int z;
int length() {return x+y+z;}};

你什么时候会选择使用struct什么时候在C++中使用类?

当我定义functorsPOD时,我使用struct。否则我使用class

// '()' is public by default!struct mycompare : public std::binary_function<int, int, bool>{bool operator()(int first, int second){ return first < second; }};
class mycompare : public std::binary_function<int, int, bool>{public:bool operator()(int first, int second){ return first < second; }};

如果你正在编写一个内部C++但API可以由C或C++代码调用的库,你可以在C++中使用“struct”。你只需制作一个包含structs和全局API函数的标头,这些函数将暴露给C和C++代码,如下所示:

// C access Header to a C++ library#ifdef __cppextern "C" {#endif
// Put your C struct's herestruct foo{...};// NOTE: the typedef is used because C does not automatically generate// a typedef with the same name as a struct like C++.typedef struct foo foo;
// Put your C API functions herevoid bar(foo *fun);
#ifdef __cpp}#endif

然后,您可以使用C++代码在C++文件中编写一个函数bar(),并使其可从C调用,两个世界可以通过声明的结构共享数据。当然,混合C和C++还有其他注意事项,但这是一个简化的示例。

在现有的答案中有很多误解。

classstruct都声明了一个类。

是的,您可能需要在类定义中重新排列访问修改关键字,具体取决于您用于声明类的关键字。

但是,除了语法之外,选择一个而不是另一个的只有原因是约定/风格/偏好。

对于没有成员函数的类,有些人喜欢坚持使用struct关键字,因为结果定义“看起来像”C中的简单结构。

类似地,有些人喜欢使用class关键字来表示具有成员函数和private数据的类,因为它上面写着“class”,因此看起来像他们最喜欢的面向对象编程书籍中的示例。

现实情况是,这完全取决于你和你的团队,它对你的程序没有任何影响。

以下两个类除了名称之外,在各个方面都是完全等价的:

struct Foo{int x;};
class Bar{public:int x;};

您甚至可以在重新声明时切换关键字:

class Foo;struct Bar;

(虽然这打破了Visual Studio构建由于不符合,所以编译器在执行此操作时会发出警告。)

以下表达式的值均为true:

std::is_class<Foo>::valuestd::is_class<Bar>::value

但是,请注意,当重新定义时您不能切换关键字;这只是因为(根据单定义规则)跨翻译单元的重复类定义必须“由相同的令牌序列组成”。这意味着您甚至不能将const int member;int const member;交换,并且与classstruct的语义学无关。

当我需要创建POD类型或仿函数时,我使用结构。

班。

默认情况下,类成员是私有的。

class test_one {int main_one();};

相当于

class test_one {private:int main_one();};

所以如果你尝试

int two = one.main_one();

我们会得到一个错误:main_one is private,因为它无法访问。我们可以通过指定它的公共ie来初始化它来解决它

class test_one {public:int main_one();};

结构。

结构是一个类,其中成员默认是公共的。

struct test_one {int main_one;};

意味着main_one是私有的

class test_one {public:int main_one;};

我为数据结构使用结构,其中成员可以取任何值,它是这样比较容易

class相比,struct的优点是它节省了一行代码,如果坚持“首先是公共成员,然后是私有成员”。有鉴于此,我发现关键字class毫无用处。

这是只使用struct而不使用class的另一个原因。C++的一些代码风格指南建议对函数宏使用小写字母,理由是当宏转换为内联函数时,名称不需要更改。这里也一样。你有一个不错的C风格结构,有一天,你发现你需要添加一个构造函数,或者一些方便的方法。你会把它改成class吗?到处都是?

区分structclasses实在是太麻烦了,我们要做的是编程。就像C++的许多问题一样,它源于对向后兼容的强烈渴望。

正如其他人所指出的

  • 除了默认可见性之外,两者都是等效的
  • 可能有理由被迫使用一个或另一个,无论出于什么原因

关于何时使用Stroustrup/Sutter有一个明确的建议:

如果类具有不变量,则使用class;如果数据成员可以独立变化,则使用struct

但是,请记住,将…声明为类(class X;)并将其定义为struct(struct X { ... })是不明智的。它可能在某些链接器上工作(例如g++),在其他链接器上可能会失败(例如MSVC),所以你会发现自己陷入了开发人员的地狱。

默认情况下,所有类成员都是私有的,所有结构成员都是公共的。类有默认的私有基,结构有默认的公共基。C的结构不能有成员函数,就像C++的情况一样,我们可以将成员函数添加到结构中。除了这些差异,我没有发现任何令人惊讶的地方。

structclass本质上是一样的,尽管在可见性方面有不同的默认值,struct默认值是公共的,class默认值是私有的。您可以通过适当使用privatepublic将其中一个更改为另一个。它们都允许继承、方法、构造函数、析构函数以及面向对象语言的所有其他优点。

然而,两者之间的一个巨大区别是struct作为关键字在C中被支持,而class不是。这意味着可以在包含文件中使用struct,可以#include到C++或C中,只要struct是纯C风格struct,并且包含文件中的所有其他内容都与C兼容,即没有C++特定的关键字,如privatepublic,没有方法,没有继承等。

C样式struct可以与其他支持使用C样式struct在接口上来回传输数据的接口一起使用。

C风格struct是一种描述内存区域布局的模板(不是C++模板,而是一种模式或模板)。多年来,可以从C和C插件(这里看看你Java和Python和Visual Basic)中使用的接口已经创建,其中一些可以使用C风格struct

只是为了从C++20标准的角度来解决这个问题(从N4860开始工作)…

是一个类型。关键字“class”和“struct”(和“union”)在C++语法中是类密钥s,选择classstruct的唯一功能意义是:

默认情况下,类密钥确定……访问是公共的还是私有的(11.9)。

数据成员默认可访问性

class关键字导致默认私有成员,'struct关键字导致默认公共成员,这在11.9.1中的示例中有记录:

X类int a;//X::a 默认是私有的:使用的类

… vs…

struct S{

struct S{int a;//S::a 默认是公共的:使用结构

基类默认可访问性

1.9还说:

在基类没有访问指定符的情况下,当使用类密钥struct定义派生类时假设public,当使用类密钥class定义类时假设private

需要一致使用struct或class的情况…

这里有一个需求:

在类模板的重新声明、局部特化、显式特化或显式实例化中,类密钥应与原始类模板声明(9.2.8.3)相一致。

…在任何精心设计的类型说明符中,enum关键字应用于指代枚举(9.7.1),union类密钥应用于指代union(11.5),classstruct类密钥应为用于引用非联合类(11.1)。

提供以下示例(当需要一致性没有时):

struct S{}s;类S*p=&s;//OK

尽管如此,一些编译器可能会对此发出警告。


有趣的是,虽然您使用structclassunion创建的类型都称为“类”,但我们有…

标准布局结构是使用类密钥struct类密钥class定义的标准布局类。

…所以在标准中,当谈论标准布局结构时,它使用“struct”来暗示“不是联合”。

我很好奇在其他术语中是否有类似的“struct”用法,但是对标准进行详尽的搜索是一项太大的工作。欢迎评论。

在我的主要语言C++编程多年后,我得出一个死的结论,这是另一个C++愚蠢的特性。

两者之间没有真正的区别,也没有理由我应该花额外的时间来决定我应该将我的实体定义为结构还是类。

要回答这个问题,请随时将您的实体定义为结构。默认情况下成员将是公共的,这是常态。但更重要的是,默认情况下继承将是公共的。受保护的继承,甚至更糟的是私有继承,是例外。

我从来没有遇到过私有继承是正确的做法的情况。是的,我试图发明问题来使用私有继承,但它不起作用。Java,如果你不使用访问器关键字,面向对象编程的角色模型默认为公共继承。顺便说一句,Java不允许继承类上的访问器关键字,它们只能被公开继承。所以你可以看到,cpp团队真的在这里倒下了。

另一个令人沮丧的事情是,如果你定义为一个类并声明为一个结构,你会得到编译警告。好像这会影响程序的性能和准确性。一个答案还指出MSVC可能会引发编译器错误。

那些在下雨的时候使用类,在发光的时候使用结构的人是基于他们被教导的内容这样做的。他们发现这不是真的。Java没有一对类的名称,只有class关键字。如果你想要一个数据结构,简单地让你所有的成员都是公共的,并且不添加函数。这在Java工作,我看没有任何问题。问题是什么?你需要4或5个字符的BOM代码来确定如何解释类实体的上下文。

如果您的程序需要面向对象的方法,您可以选择类,否则struct将满足您的大部分需求。