在什么情况下,在C ++中使用struct
和class
会更好?
在C ++中class
和struct
之间的差异是结构具有默认的public
成员和基础,并且类具有默认的private
成员和基础。类和结构都可以混合使用public
,protected
和private
成员,可以使用继承并且可以具有成员函数。
我建议使用结构作为普通旧数据结构,没有任何类似于类的特性,并使用类作为与private
数据和成员函数的聚合数据结构。
对于C ++,结构和类之间确实没有太大的区别。主要功能区别在于,默认情况下结构的成员是公共的,而在类中默认是私有的。否则,就语言而言,它们是等价的。
也就是说,我倾向于像在C#中一样使用C ++中的结构,类似于Brian所说的。结构是简单的数据容器,而类用于需要对数据执行操作的对象,而不仅仅是保持数据。
回答我自己的问题(无耻地),如前所述,访问权限是C ++中它们之间的唯一区别。
我倾向于仅使用结构进行数据存储。如果它更容易处理数据,我将允许它获得一些辅助函数。但是,只要数据需要流控制(即维护或保护内部状态的getter / setter)或开始获取任何主要功能(基本上更像对象),它就会“升级”到类以更好地传达意图。
它们几乎是一回事。感谢C ++的神奇之处,一个struct可以保存函数,使用继承,使用“new”创建,就像一个类一样
唯一的功能区别是一个类以私有访问权限开头,而一个结构以public开头。这是与C保持向后兼容性。
在实践中,我总是使用结构作为数据持有者和类作为对象。
默认情况下,类成员是私有的。
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是一个默认情况下成员是公共的类。
struct test_one {
int main_one;
};
意味着main_one
是私人的,即
class test_one {
public:
int main_one;
};
我将结构用于数据结构,其中成员可以获取任何值,这样更容易。
它们具有不同的默认值(class
默认为私有,struct
默认为public),因此理论上它们完全可以互换。
所以,如果我只想打包一些信息来移动,我使用一个结构,即使我在那里放了几个方法(但不是很多)。如果它是一个大多数不透明的东西,主要用途是通过方法,而不是直接对数据成员,我使用完整的类。
默认情况下,结构具有公共访问权限,默认情况下类具有私有访问权限。
我个人使用数据传输对象的结构或值对象。当我这样使用时,我将所有成员声明为const以防止被其他代码修改。
struct
优于class
的一个优点是它可以节省一行代码,如果坚持“第一个公共成员,那么私有”。在这种情况下,我发现关键字class
无用。
这是仅使用struct
而不使用class
的另一个原因。 C ++的一些代码风格指南建议对函数宏使用小写字母,其基本原理是当宏转换为内联函数时,名称不需要更改。同样在这里。你有一个漂亮的C风格的结构,有一天,你发现你需要添加一个构造函数,或者一些方便的方法。你把它变成了class
吗?到处?
区分struct
s和class
es是太麻烦了,开始做我们应该做的事情 - 编程。像许多C ++的问题一样,它源于对向后兼容性的强烈渴望。
正如其他人所指出的那样
有关何时使用Stroustrup / Sutter的明确建议:
Use class if the class has an invariant; use struct if the data members can vary independently
但是,请记住,转发声明是不明智的。作为一个类(class X;
)并将其定义为struct(struct X { ... }
)。它可能适用于某些链接器(例如,g ++)并且可能在其他链接器上失败(例如,MSVC),因此您将发现自己处于开发人员的地狱中。
从技术上讲,两者在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; }
};
正如其他人所指出的那样,实际上只存在两种语言差异:
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类型”实际含义的一些好解释的帖子:What are POD types in C++?)
当我需要创建POD类型或仿函数时,我使用结构。
默认情况下,所有类成员都是私有的,并且所有struct成员都是公共的。类具有默认私有基础,而Struct具有默认公共基础。在C的情况下,struct不能具有成员函数,在C ++的情况下,我们可以将成员函数添加到结构中。除了这些差异,我没有发现任何令人惊讶的事情。
我只在需要保存一些数据而没有任何与之关联的成员函数(对成员数据进行操作)并直接访问数据变量时才使用struct。
例如:从文件和套接字流等读取/写入数据。在函数参数太多而函数语法看起来过于冗长的结构中传递函数参数。
从技术上讲,除了默认可访问性之外,类和结构之间没有太大区别。更多内容取决于编程风格如何使用它。
我认为Structs旨在作为数据结构(如多数据类型的信息数组),并且类用于代码打包(如子程序和函数的集合)。
:(
我从不在C ++中使用“struct”。
我想不到你想要私人会员时使用结构的场景,除非你故意让人感到困惑。
似乎使用结构更多地是关于如何使用数据的语法指示,但我宁愿只创建一个类并尝试在类的名称或通过注释进行显式化。
EG
class PublicInputData {
//data members
};
现有答案中存在许多误解。
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
的语义无关。
我唯一一次使用struct而不是类是在函数调用中使用它之前声明一个仿函数,并且为了清晰起见希望最小化语法。例如。:
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
来自C++ FAQ Lite:
结构的成员和基类默认是公共的,而在类中,它们默认为私有。注意:您应该明确公开,私有或保护基类,而不是依赖于默认值。
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中做的一样,但我发现必须将消息解码为类的开销通常是不值得的。
如果要编写内部为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 ++时还有其他一些注意事项,但这是一个简化的例子。
正如每个人所说,唯一真正的区别是默认访问。但是,当我不想使用简单的数据类进行任何类型的封装时,我特别使用struct,即使我实现了一些辅助方法。例如,当我需要这样的东西时:
struct myvec {
int x;
int y;
int z;
int length() {return x+y+z;}
};
当您提供与C ++兼容的C语言接口时,结构(更常见的是PODs)非常方便,因为它们可以跨语言边界和链接器格式移植。
如果你不关心这一点,那么我认为使用“struct”代替“class”是一个很好的意向沟通者(正如@ZeroSignal所说)。结构也具有更可预测的复制语义,因此它们对于您打算写入外部媒体或通过线路发送的数据非常有用。
结构对于各种元编程任务也很方便,比如只显示一堆依赖类型构造的特征模板:
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
......但这真的只是利用struct的默认保护级别是公开的......