在哪些情况下,在C ++中使用struct
与class
会更好?
答案 0 :(得分:706)
C ++中class
和struct
之间的差异是结构具有默认的public
成员,而基类和类具有默认的private
成员和基础。类和结构都可以混合使用public
,protected
和private
成员,可以使用继承并且可以具有成员函数。
我建议使用结构作为普通旧数据结构而不使用任何类似于类的特性,并使用类作为具有private
数据和成员函数的聚合数据结构。
答案 1 :(得分:198)
正如其他所有人都指出的那样,实际上只存在两种语言差异:
struct
默认为公共访问,class
默认为私人访问。struct
默认为public
继承,class
默认为private
继承。 (具有讽刺意味的是,与C ++中的许多内容一样,默认值是向后的:public
继承是迄今为止更常见的选择,但人们很少声明struct
只是为了节省输入“{{1 “关键字。但实践中的真正区别在于声明构造函数/析构函数的public
/ class
和不构造函数的析构函数。对于“普通旧数据”POD类型有一定的保证,一旦你接管了类的构造,它就不再适用了。为了明确这一区别,许多人故意仅将struct
用于POD类型,如果他们要添加任何方法,请使用struct
es。下面两个片段之间的区别是没有意义的:
class
(顺便提一下,这里有一个关于“POD类型”实际含义的一些好解释的帖子:What are POD types in C++?)
答案 2 :(得分:134)
现有答案中存在许多误解。
Both class
and struct
declare a class.
是的,您可能需要在类定义中重新排列访问修改关键字,具体取决于您用于声明类的关键字。
但是,除了语法之外,仅选择其中一个的原因是约定/样式/首选项。
有些人喜欢在没有成员函数的情况下坚持使用struct
关键字,因为结果定义“看起来像”来自C的简单结构。
类似地,有些人喜欢将class
关键字用于具有成员函数和private
数据的类,因为它上面写着“类”,因此看起来像他们最喜欢的关于对象的书中的示例 - 面向编程。
现实情况是,这完全取决于您和您的团队,并且它对您的计划没有任何影响。
除了名字之外,以下两个类绝对等同于:
struct Foo
{
int x;
};
class Bar
{
public:
int x;
};
您甚至可以在重新声明时切换关键字:
class Foo;
struct Bar;
(虽然this breaks Visual Studio builds由于不符合,但编译器会在您执行此操作时发出警告。)
并且以下表达式都评估为true:
std::is_class<Foo>::value
std::is_class<Bar>::value
请注意,重新定义时无法切换关键字;这只是因为(根据单一定义规则)跨翻译单元的重复类定义必须“由相同的标记序列组成”。这意味着您甚至无法与const int member;
交换int const member;
,也与class
或struct
的语义无关。
答案 3 :(得分:53)
我唯一一次使用struct而不是类是在函数调用中使用它之前声明一个仿函数,并且为了清晰起见希望最小化语法。 e.g:
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
答案 4 :(得分:34)
来自C++ FAQ Lite:
结构的成员和基类默认是公共的,而在类中,它们默认为private。注意:您应该明确公开,私有或保护您的基类,而不是依赖于默认值。
struct和class在功能上是等价的。
好的,足够的那个干净的技术谈话。在情感上,大多数开发人员在类和结构之间做出了很强的区分。结构只是感觉像一堆开放的位,几乎没有封装或功能。课程感觉像是一个生活和负责任的社会成员,拥有智能服务,强大的封装屏障和明确的界面。既然这是大多数人已经拥有的内涵,那么你应该使用struct关键字,如果你有一个方法很少且有公共数据的类(这些东西确实存在于设计良好的系统中!),否则你应该使用这个类关键词。
答案 5 :(得分:21)
结构对我有用的一个地方就是我有一个系统从另一个系统接收固定格式的消息(例如,一个串口)。您可以将字节流转换为定义字段的结构,然后轻松访问字段。
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中做的一样,但我发现必须将消息解码为类的开销通常是不值得的。
答案 6 :(得分:16)
如果要编写内部为C ++但可以通过C或C ++代码调用API的库,则可以在C ++中使用“struct”。您只需创建一个包含结构和全局API函数的标头,并将这些函数公开给C和C ++代码:
// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif
// Put your C struct's here
struct 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 here
void bar(foo *fun);
#ifdef __cpp
}
#endif
然后,您可以使用C ++代码在C ++文件中编写函数bar(),并使其可以从C调用,并且两个世界可以通过声明的struct共享数据。当然,在混合C和C ++时还有其他注意事项,但这是一个简化的例子。
答案 7 :(得分:15)
正如每个人所说,唯一真正的区别是默认访问。但是,当我不想使用简单的数据类进行任何类型的封装时,我特别使用struct,即使我实现了一些辅助方法。例如,当我需要这样的东西时:
struct myvec {
int x;
int y;
int z;
int length() {return x+y+z;}
};
答案 8 :(得分:9)
当你提供与C ++兼容的C ++兼容接口时,结构(PODs,更一般地说)是很方便的,因为它们可以跨语言边界和链接器格式移植。
如果你不关心这个问题,那么我认为使用“struct”代替“class”是一个很好的意向沟通者(正如@ZeroSignal所说)。结构也具有更可预测的复制语义,因此它们对于您打算写入外部媒体或通过线路发送的数据非常有用。
结构对于各种元编程任务也很方便,比如只暴露一堆依赖类型定义的特征模板:
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
......但这真的只是利用struct的默认保护级别公开...
答案 9 :(得分:8)
对于C ++,结构和类之间确实没有太大的区别。主要功能区别在于,默认情况下结构的成员是公共的,而在类中默认是私有的。否则,就语言而言,它们是等价的。
也就是说,我倾向于像在C#中一样使用C ++中的结构,类似于Brian所说的。结构是简单的数据容器,而类用于需要对数据进行操作的对象,而不仅仅是保持它。
答案 10 :(得分:7)
回答我自己的问题(无耻地),如前所述,访问权限是C ++中它们之间的唯一区别。
我倾向于仅使用结构进行数据存储。如果它更容易处理数据,我将允许它获得一些辅助函数。但是,只要数据需要流控制(即维护或保护内部状态的getter / setter)或开始获取任何主要功能(基本上更像对象),它就会“升级”到类以更好地传达意图。
答案 11 :(得分:4)
他们几乎是一回事。感谢C ++的神奇之处,结构可以保存函数,使用继承,使用“new”创建,就像类一样
唯一的功能区别是一个类以私有访问权限开头,而一个结构以public开头。这是与C维持向后兼容。
实际上,我总是使用结构作为数据持有者和类作为对象。
答案 12 :(得分:3)
默认情况下,类成员是私有的。
class test_one {
int main_one();
};
相当于
class test_one {
private:
int main_one();
};
所以如果你试试
int two = one.main_one();
我们会收到错误:main_one is private
因为无法访问。我们可以
通过指定公共即
class test_one {
public:
int main_one();
};
struct是默认情况下成员公开的类。
struct test_one {
int main_one;
};
意味着main_one
是私有的,即
class test_one {
public:
int main_one;
};
我将结构用于数据结构,其中成员可以获取任何值,就是这样 这样更容易。
答案 13 :(得分:2)
默认情况下,Structs具有公共访问权限,默认情况下,类具有私有访问权限。
我个人使用数据传输对象的结构或值对象。当我这样使用时,我将所有成员声明为const以防止被其他代码修改。
答案 14 :(得分:2)
它们与默认值不同(class
默认为私有,struct
默认为public),因此理论上它们完全可以互换。
所以,如果我只想打包一些信息来移动,我使用一个结构,即使我在那里放了一些方法(但不是很多)。如果它是一个大多数不透明的东西,主要用途是通过方法,而不是直接对数据成员,我使用完整的类。
答案 15 :(得分:2)
struct
优于class
的一个优点是,它可以保存一行代码,如果遵守&#34;首先是公共成员,那么私有&#34;。有鉴于此,我发现关键字class
无用。
以下是仅使用struct
而不使用class
的另一个原因。 C ++的一些代码风格指南建议对函数宏使用小写字母,其基本原理是当宏转换为内联函数时,名称不应该被更改。同样在这里。你有一个漂亮的C风格的结构,有一天,你发现你需要添加一个构造函数,或者一些方便的方法。你把它改成class
吗?到处?
区分struct
和class
es太麻烦了,不妨碍我们应该做的事情 - 编程。像许多C ++的问题一样,它源于对向后兼容性的强烈渴望。
答案 16 :(得分:1)
struct
和class
的内幕相同,尽管可见性的默认值不同,struct
的默认值是public,class
的默认值是private。您可以通过适当使用private
和public
将其中一个更改为另一个。它们都允许继承,方法,构造函数,析构函数以及面向对象语言的所有其他优点。
但是,两者之间的巨大区别是C支持struct
作为关键字,而class
不支持。这意味着只要struct
是普通的C风格#include
,所有内容都可以在包含文件中使用struct
,而包含文件可以struct
进入C ++或C语言包含文件中的else与C兼容,即没有C ++特定的关键字,例如private
,public
,没有方法,没有继承等,等等。
C样式struct
可以与其他支持使用C样式struct
的接口一起使用,以在该接口上来回携带数据。
C样式struct
是一种描述内存区域布局的模板(不是C ++模板,而是一种模式或模板)。多年以来,已经创建了可用于C和C插件的接口(在这里您将看到Java,Python和Visual Basic),其中一些接口可以使用C样式struct
。
答案 17 :(得分:1)
默认情况下,所有类成员都是私有的,默认情况下,所有结构成员都是公共的。 类具有默认的私有基础,而Struct具有默认的公共基础。在C的情况下,结构不能具有成员函数,而在C ++的情况下,可以将成员函数添加到结构中。除了这些差异之外,我对它们没有任何惊讶。
答案 18 :(得分:1)
正如其他人指出的
Stroustrup / Sutter中有关于何时使用的明确建议:
Use class if the class has an invariant; use struct if the data members can vary independently
但是,请记住,向前声明sth是不明智的。作为一个类(class X;
)并将其定义为struct(struct X { ... }
)。
它可能在某些链接器(例如g ++)上工作,而在其他链接器(例如MSVC)上可能失败,因此您会发现自己在开发人员的地狱中。
答案 19 :(得分:1)
只是为了从 C++20 标准的角度解决这个问题(从 N4860 工作)...
class 是一种类型。关键字“class
”和“struct
”(和“union
”)是 - 在 C++ 语法中 - class-keys,并且是唯一的函数选择 class
或 struct
的意义在于:
class-key 决定了 ... 默认情况下访问是公开的还是私有的(11.9)。
11.9.1 中的示例记录了 class
关键字导致默认私有成员和 `struct 关键字导致默认公共成员:
类 X { 一个; // X::a 默认是私有的:使用的类
...对...
<块引用>结构体{ 一个; // S::a 默认是公开的:使用结构体
1.9 还说:
<块引用>如果基类没有访问说明符,当派生类使用class-key {{当使用 class-key public
定义类时,假定为 1}} 和 struct
。
有一个要求:
<块引用>在类模板的重新声明、部分特化、显式特化或显式实例化中,class-key 应与原始类模板声明 (9.2.8.3) 一致。
<块引用>...在任何elaborated-type-specifier中,private
关键字应用于引用枚举(9.7.1),class
class-key 应用于指代 enum
(11.5),并且 union
或 union
class-key 应为
用于指代非联合类 (11.1)。
提供了以下示例(当不需要一致性时):
<块引用>struct S { } s; 类 S* p = &s; // 好的
不过,一些编译器可能会对此发出警告。
有趣的是,虽然您使用 class
、struct
和 struct
创建的类型都称为“类”,但我们有...
standard-layout struct 是使用 class-key class
或 class-key 定义的标准布局类union
。
...所以在Standardese 中,当谈到标准布局结构 时,它使用“struct”来暗示“不是联合”。
我很好奇在其他术语中是否有类似的“struct”用法,但是对标准进行详尽的搜索是一项艰巨的工作。对此欢迎发表评论。
答案 20 :(得分:1)
当我需要创建POD类型或仿函数时,我会使用结构。
答案 21 :(得分:1)
您何时会选择使用struct 什么时候在C ++中使用类?
我在定义struct
和functors
时使用POD
。否则我使用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; }
};
答案 22 :(得分:1)
从技术上讲,两者在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学生 - 享受。
答案 23 :(得分:0)
我只在需要保存一些数据而没有任何与之关联的成员函数(对成员数据进行操作)并直接访问数据变量时才使用struct。
例如:从文件和套接字流中读取/写入数据等。在函数参数太多且函数语法看起来过于冗长的结构中传递函数参数。
从技术上讲,除了默认可访问性之外,类和struture之间没有太大区别。 更多内容取决于编程风格如何使用它。
答案 24 :(得分:-4)
我认为Structs旨在作为数据结构(如多数据类型的信息数组),并且类用于代码打包(如子程序和函数的集合)。
:(
答案 25 :(得分:-6)
我从不在C ++中使用“struct”。
我想不到你想要私人会员时使用结构的场景,除非你故意试图让人困惑。
似乎使用结构更多地是关于如何使用数据的语法指示,但我宁愿只创建一个类并尝试在类的名称或通过注释进行显式化。
E.g。
class PublicInputData {
//data members
};