在什么情况下,在C ++中使用struct
vs 会更好class
?
在什么情况下,在C ++中使用struct
vs 会更好class
?
Answers:
C ++中a class
和a 之间的区别在于struct
,结构具有默认public
成员和基数,而类具有默认private
成员和基数。两个类和结构可具有的混合物public
,protected
和private
构件,可以使用继承并且可以具有成员函数。
我建议将结构用作没有任何类功能的纯旧数据结构,并建议将类用作具有private
数据和成员函数的聚合数据结构。
正如其他所有人所指出的,实际上只有两种实际语言差异:
struct
默认为公共访问,class
默认为私有访问。struct
默认为public
继承,class
默认为private
继承。(具有讽刺意味的是,与C ++中的许多事情一样,默认值是向后的:public
到目前为止,继承是更常见的选择,但是人们很少声明struct
s只是为了省去键入“ public
”关键字。但在实践中,真正的差别是间class
/ struct
声明构造函数/析构函数不和的。对于“普通数据” POD类型有某些保证,一旦您接管了班级的建设,这些保证将不再适用。为了清楚地区分,许多人故意将struct
s用于POD类型,并且,如果他们要添加任何方法,请使用class
es。否则,以下两个片段之间的区别是没有意义的:
class X
{
public:
// ...
};
struct X
{
// ...
};
(顺便说一下,这里的一个线程对“ POD类型”的实际含义做了一些很好的解释:C ++中的POD类型是什么?)
struct
还是class
不影响对象是POD还是应定义副本构造函数/析构函数。成员函数也与POD无关。当我重新阅读您写的内容时,我发现您没有其他建议,但当前的措辞令人困惑
现有答案中存在很多误解。
是的,您可能必须在类定义中重新排列访问修改关键字,具体取决于您用来声明该类的关键字。
但是,除了语法之外,唯一选择一个的另一个原因是约定/样式/首选项。
有些人喜欢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>::value
std::is_class<Bar>::value
不过请注意,重新定义时不能切换关键字;这仅仅是因为(按照一定义规则)跨翻译单元的重复类定义必须“由相同的令牌序列组成”。这意味着你甚至无法交流const int member;
与int const member;
,并有无关的语义class
或struct
。
class foo { public: ... };
而另一个可以具有struct foo { ... };
根据“绝对等效”的说法必须成立的声明。原因是不完整的声明struct foo;
和class foo;
是可以互换的。这些没有指定类主体,因此它们对访问布局一无所知。
Foo
与Bar
依然当量/相同类型。我确实确保说“在重新声明时 ” 并举一个例子。想一想,我会在答案中阐明这一点,以确保我不会误导人们进入UB
我唯一使用结构而不是类的方法是在函数调用中使用函子之前声明函子,并且为了清楚起见,希望最小化语法。例如:
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
结构的成员和基类默认情况下是公共的,而在类中,它们默认是私有的。注意:应将基类显式设置为公共,私有或受保护,而不要依赖默认值。
struct和class在功能上是等效的。
好的,足够的干净利落的技术讨论。从情感上讲,大多数开发人员在类和结构之间做出强烈区分。结构只是感觉像是一堆开放的位,几乎没有封装或功能性的方式。班级感觉像是一个有活力的社会成员,拥有智能的服务,强大的封装障碍和明确定义的界面。因为这是大多数人已经拥有的含义,所以如果您有一个方法很少且具有公共数据的类(这种情况确实存在于设计良好的系统中!),则应该使用struct关键字,否则,您可能应该使用该类关键词。
结构对我有用的一个地方是当我的系统正在从另一个系统接收固定格式的消息(例如,串行端口)时。您可以将字节流转换为定义字段的结构,然后轻松访问这些字段。
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中所做的相同,但是我发现必须将消息解码为类的开销通常是不值得的。
operator >>
一类,而不是写的processMessage
功能,这将使你的C ++看起来更像适当的C ++而不是像C.
__packed__
结构并具有endian感知的ifdef实现(您需要在字节序与外部数据源相反的计算机上翻转顺序)正在提供)。它不是很漂亮,但是我习惯于以可移植的方式打包/解压嵌入式平台上远程外围设备的寄存器。
char
类型,可以免于别名。但是,尽管存在一个不同的问题,但仍然存在一个问题:char*
如果确实没有在该地址处初始化后一种类型的任何对象,则将a 强制转换为另一种类型是UB,因为它违反了生命周期规则。Afaik,即使目标类型是微不足道的可构造的,仅分配内存也不足以使C ++正式允许将该内存视为该类型。
如果要编写内部结构为C ++的库,则可以在C ++中使用“结构”,但是可以用C或C ++代码调用该API。您只需制作一个包含结构体和全局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调用,并且两个世界都可以通过声明的结构共享数据。当混合使用C和C ++时,当然还有其他注意事项,但这是一个简化的示例。
要回答我自己的问题(无耻地),正如已经提到的那样,访问特权是C ++中它们之间的唯一区别。
我倾向于仅将结构用于数据存储。如果它使处理数据更加容易,我将允许它获得一些帮助功能。但是,一旦数据需要流控制(即保持或保护内部状态的吸气剂/设置剂)或开始获取任何主要功能(基本上更像对象),它将被“升级”到一个类中以更好地传达意图。
当您要提供具有C ++实现的C兼容接口时,结构(POD,通常来说)比较方便,因为它们可以跨语言边界和链接器格式移植。
如果您不必担心,那么我认为使用“ struct”而不是“ class”可以很好地传达意图(如@ZeroSignal所述)。结构还具有更可预测的复制语义,因此它们对于打算写入外部媒体或通过网络发送的数据很有用。
结构对于各种元编程任务也很方便,例如仅公开一堆依赖的typedef的特征模板:
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
...但这实际上只是利用了struct的默认保护级别是公开的...
正如其他人指出的
Stroustrup / Sutter明确建议何时使用:
但是,请记住,向前声明sth是不明智的。作为类(class X;
)并将其定义为struct(struct X { ... }
)。它可能在某些链接器(例如,g ++)上起作用,而在其他链接器(例如,MSVC)上可能失败,因此您会发现自己陷入了开发人员的泥潭。
class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }
事情不仅会编译并与MSVC 2017一起运行,它甚至还会产生明确的警告,该警告Foo
已声明为struct
但定义为class
。但是我也清楚地记得,我们的团队花了半天的时间才发现该愚蠢的错误。我不确定当时使用的MSVC版本。
class
还是struct
在前向声明上,并且按照标准,两者可以自由互换(尽管众所周知VS警告;我一直认为那只是为了避免明显的程序员错误)。这里没有什么味道。您确定这不是违反ODR的错误吗?
struct
-forwards 替换为class
-forwards,问题就消失了。从今天起,我也觉得很奇怪。如果您能对此有所了解,我会很高兴。
默认情况下,班级成员是私人的。
class test_one {
int main_one();
};
相当于
class test_one {
private:
int main_one();
};
所以如果你尝试
int two = one.main_one();
我们将收到一个错误:main_one is private
因为它不可访问。我们可以通过指定一个public来初始化它来解决它
class test_one {
public:
int main_one();
};
struct是一类,默认情况下成员是公共的。
struct test_one {
int main_one;
};
手段main_one
是私人的,即
class test_one {
public:
int main_one;
};
我将结构用于成员可以取任何值的数据结构,这样比较容易。
struct
over 的优点class
是,如果坚持“先公开成员,然后私有”,那么它将节省一行代码。因此,我发现关键字class
没有用。
这是仅使用struct
永不使用的另一个原因class
。一些C ++的代码风格指南建议对函数宏使用小写字母,其基本原理是,当宏转换为内联函数时,无需更改名称。同样在这里。您拥有了不错的C样式结构,有一天,您发现需要添加一个构造函数或一些便捷方法。您将其更改为class
吗?到处?
区分struct
s和class
es太麻烦了,进入了做我们应该做的事情的方式-编程。像许多C ++问题一样,它源于对向后兼容性的强烈渴望。
class
?您是否认为用struct
关键字定义的类不能具有成员函数或构造函数?
joe()
必须用class
关键字定义?每个至少有4位int
成员的课程都必须使用struct
关键字定义?
struct
,带方法聚合定义为class
”。太麻烦了。
这两个struct
和class
是引擎盖下一样,虽然有不同的默认值,以知名度,struct
缺省为public,class
默认为私有。您可以使用private
和适当地将其中一个更改为另一个public
。它们都允许继承,方法,构造函数,析构函数以及面向对象语言的所有其他优点。
但是,两者之间的巨大差异struct
是C支持关键字,class
而不支持C。这意味着,可以使用一个struct
包含文件中,可以是#include
进入或者C ++或C,只要struct
是普通的C风格struct
,并在一切包括文件兼容C,即没有C ++特定的关键字,例如private
,public
无方法,没有继承等,等等。
AC风格struct
可以与其他支持C风格的接口一起使用,struct
以在接口上来回传输数据。
AC样式struct
是一种描述内存区域布局的模板(不是C ++模板,而是一种模式或模具)。多年以来,已经创建了可用于C和C插件的接口(在这里为您介绍Java和Python和Visual Basic),其中一些可用于C样式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,何时选择使用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; }
};
std::binary_function<>
不仅被弃用,c ++ 17甚至将其删除。
我认为Structs旨在作为一种数据结构(如信息的多数据类型数组),而类是为代码打包而设计的(如子例程和函数的集合)。
:(
我从不在C ++中使用“结构”。
我无法想像一个场景,当您想要私有成员时会使用struct,除非您故意要造成混淆。
似乎使用structs更像是如何使用数据的语法指示,但我宁愿仅创建一个类并尝试以类的名称或通过注释将其显式表示。
例如
class PublicInputData {
//data members
};
struct
很明确地宣布该类的成员默认情况下将是公共的?