C++中的结构体和类有什么区别?
题
这个问题是 已经在 C#/.Net 的上下文中询问过.
现在我想了解 C++ 中结构体和类之间的区别。请讨论技术差异以及在 OO 设计中选择其中之一的原因。
我将从一个明显的区别开始:
- 如果你不指定
public:
或者private:
, ,结构体的成员默认是公共的;默认情况下,类的成员是私有的。
我确信在 C++ 规范的不起眼的角落中还可以发现其他差异。
解决方案
您忘记了类和结构之间棘手的第二个区别。
引用标准(C++98 到 C++11 中的第 11.2.2 节):
在没有 访问说明符对于基类,在声明派生类时假设公众是公众的 结构体 并且在声明类时假定为 private 班级.
为了完整起见,类和结构之间更广为人知的区别在(11.2)中定义:
用关键字定义的类的成员 班级 是 私人的 默认情况下。用关键字定义的类的成员 结构体 或者 联盟是 民众 默认情况下。
附加区别:关键字 class
可用于声明模板参数,而 struct
不能这样使用关键字。
其他提示
引用 C++ 常见问题解答,
7.8]关键字结构和类之间有什么区别?
默认情况下,结构的成员和基础类是公共的,而在课堂上,它们默认为私有。笔记:您应该使基础类明确公开,私人或受保护,而不是依靠默认设置。
结构和类在功能上是等效的。
好的,足够的吱吱作响的干净技术谈话。在情感上,大多数开发人员在班级和结构之间做出了强烈的区别。一个结构只是感觉像是一堆开放的碎屑,几乎没有封装或功能。一个班级感觉就像是一个具有智能服务,强大的封装障碍和定义明确的界面的社会成员和负责任的成员。由于这是大多数人已经拥有的含义,因此,如果您的类具有很少的方法并且具有公共数据的类别(确实存在于设计良好的系统中!),则可能应该使用struct关键字,但是否则,您可能应该使用类关键词。
值得记住的是 C++ 的起源以及与 C 的兼容性。
C有结构,它没有封装的概念,所以一切都是公共的。
在采用面向对象方法时,默认情况下公开通常被认为是一个坏主意,因此在创建一种本身有利于 OOP 的 C 形式时(您可以在 C 中进行 OO,但它不会帮助您),这就是C++ 中的想法(最初是“C With Classes”),默认情况下将成员设置为私有是有意义的。
另一方面,如果 Stroustrup 改变了语义 struct
因此它的成员默认是私有的,它会破坏兼容性(随着标准的分歧,它不再那么常见,但所有有效的 C 程序也是有效的 C++ 程序,这对 C++ 的立足点产生了很大的影响)。
所以一个新的关键字, class
被引入为与结构完全相同,但默认情况下是私有的。
如果 C++ 从头开始,没有历史,那么它可能只有一个这样的关键字。它也可能不会产生它所产生的影响。
一般来说,人们在做类似 C 中如何使用结构体的事情时会倾向于使用结构体;公共成员,没有构造函数(只要它不在联合体中,您就可以 能 结构中有构造函数,就像类一样,但人们往往不这样做),没有虚方法等。由于语言既可以与阅读代码的人进行交流,也可以指导机器(否则我们会坚持使用汇编和原始 VM 操作码),因此坚持这一点是个好主意。
类的成员默认是私有的。默认情况下,Struct 的成员是公共的。除此之外没有其他区别。另请参阅 这个问题.
根据斯特鲁斯特鲁普在 C++ 编程语言:
您使用哪种风格取决于环境和品味。我通常更喜欢使用
struct
对于所有数据都是公开的类。我认为此类“不是完全正确的类型,只是数据结构”。
从功能上来说,除了公/私之外没有任何区别
STRUCT 是一种抽象数据类型,它根据结构规范划分给定的内存块。结构在文件序列化/反序列化中特别有用,因为结构通常可以逐字写入文件。(IE。获取指向结构的指针,使用 SIZE 宏计算要复制的字节数,然后将数据移入或移出结构。)
类是一种不同类型的抽象数据类型,试图确保信息隐藏。在内部,可以有各种阴谋、方法、临时变量、状态变量。ETC。它们都用于向任何希望使用该类的代码提供一致的 API。
实际上,结构是关于数据的,类是关于代码的。
但是,您确实需要了解这些只是抽象概念。完全有可能创建看起来很像类的结构以及看起来很像结构的类。事实上,最早的 C++ 编译器只是将 C++ 代码翻译为 C 的预编译器。因此,这些抽象有利于逻辑思维,但不一定是计算机本身的资产。
除了每个类都是不同类型的抽象这一事实之外,类还为 C 代码命名难题提供了解决方案。由于不能有多个具有相同名称的函数,因此开发人员过去常常遵循 _() 模式。例如mathlibextreme_max()。通过将 API 分组为类,可以将类似的函数(这里我们称之为“方法”)分组在一起,并免受其他类中方法命名的影响。这允许程序员更好地组织他的代码并增加代码重用。至少在理论上是这样。
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;
}
Run on IDE
// 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;
}
2) 当从类/结构派生结构时,基类/结构的默认访问说明符是 public。并且在派生类时,默认访问说明符是 private。
例如,程序 3 编译失败,程序 4 运行正常。
// Program 3
#include <stdio.h>
class Base {
public:
int x;
};
class Derived : Base { }; // is equilalent to class Derived : private Base {}
int main()
{
Derived d;
d.x = 20; // compiler error becuase inheritance is private
getchar();
return 0;
}
Run on IDE
// Program 4
#include <stdio.h>
class Base {
public:
int x;
};
struct Derived : Base { }; // is equilalent to struct Derived : public Base {}
int main()
{
Derived d;
d.x = 20; // works fine becuase inheritance is public
getchar();
return 0;
}
唯一的其他区别是类和结构的默认继承,毫不奇怪,它们分别是私有的和公共的。
规范中没有,没有。主要区别在于程序员在两年内阅读您的代码时的期望。结构通常被假定为 POD。当您为了定义对象以外的目的而定义类型时,结构体也可用于模板元编程。
另一件需要注意的事情是,如果您更新了具有使用类的结构的旧应用程序,您可能会遇到以下问题:
旧代码具有结构,代码已被清理,并且已更改为类。然后将一两个虚拟函数添加到新的更新类中。
当虚拟函数位于类中时,编译器将在内部添加额外的指针到类数据以指向函数。
这将如何破坏旧的遗留代码,如果在旧代码中的某处使用 memfill 清除结构以将其全部清除为零,这也会破坏额外的指针数据。
- 结构体的成员默认是公共的,类的成员默认是私有的。
- 来自另一个结构或类的结构的默认继承是公共的。来自另一个结构或类的类的默认继承是私有的。
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上的。
另一个主要区别是模板。据我所知,在定义模板时可以使用类,但不能使用结构。
template<class T> // OK
template<struct T> // ERROR, struct not allowed here
使用关键字定义的类的成员
class
是private
默认情况下。使用关键字定义的类的成员struct
(或者union
) 是public
默认情况下。如果基类没有访问说明符,
public
假设当 衍生的 类已声明struct
和private
声明类时假定class
.您可以声明一个
enum class
但不是enum struct
.您可以使用
template<class T>
但不是template<struct T>
.
另请注意,C++ 标准允许您将类型前向声明为 struct
, ,然后使用 class
声明类型时,反之亦然。还, std::is_class<Y>::value
是 true
因为 Y 是 struct
和一个 class
, , 但是 false
为 enum class
.
这是一个很好的解释: http://carcino.gen.nz/tech/cpp/struct_vs_class.php
所以,再一次:在 C++ 中,结构体与类相同,只是结构体的成员默认具有公共可见性,而类的成员默认具有私有可见性。
这只是一个约定。可以创建结构来保存简单数据,但稍后会通过添加成员函数和构造函数来演变。另一方面,除了公开之外,看到任何其他东西都是不寻常的:结构体中的访问。
ISO IEC 14882-2003
9 节课
§3
结构是定义的类 类键
struct
;默认情况下,其成员和基础类(第10条)是公开的(第11条)。
其他答案提到了私有/公共默认值,(但请注意,结构是类是结构;它们不是两个不同的项目,只是定义同一项目的两种方式)。
值得注意的是(特别是因为提问者可能正在使用 MSVC++,因为他提到了“非托管”C++),如果使用以下方式声明类,Visual C++ 在某些情况下会抱怨: class
然后定义为 struct
(或者可能反过来),尽管标准说这是完全合法的。
. 。在类中,默认情况下所有成员都是私有的,但在结构中,成员默认是公共的。
对于结构,没有像构造函数和析构函数这样的术语,但是对于类,如果您不提供,编译器会创建默认值。
空结构的 Sizeof 为 0 字节,因为空类的 Sizeof 为 1 字节 结构默认访问类型是 public。结构通常应用于分组数据。
类默认访问类型是私有的,并且继承的默认模式是私有的。应该将类用于分组在该数据上操作的数据和方法。
简而言之,该约定是在目的是分组数据时使用struct,并在需要数据抽象以及可能的继承时使用类。
在C ++的结构和类中,除非明确退出引用。在其他语言中,类和结构可能具有不同的语义 - 即。对象(类的实例)可以通过参考传递,结构可以按值传递。笔记:这个问题有评论。请参阅讨论页添加到对话。
虽然其他答案暗示了这一点,但没有明确提及 - 结构是 C 兼容的,具体取决于用法;类不是。
这意味着,如果您正在编写一个想要与 C 兼容的标头,那么除了 struct 之外您别无选择(在 C 世界中,struct 不能有函数;但可以有函数指针)。
和...之间的不同 class
和 struct
是关键字之间的差异,而不是数据类型之间的差异。这两个
struct foo : foo_base { int x;};
class bar : bar_base { int x; };
两者都定义了类类型。此上下文中关键字的区别在于默认访问不同:
foo::x
是公开的并且foo_base
被公开继承bar::x
是私人的并且bar_base
是私人继承的
类仅在软件工程背景下才有意义。在数据结构和算法的上下文中,类和结构并没有那么不同。没有任何规则限制类的成员必须被引用。
当与大量没有班级的人一起开发大型项目时,您最终可能会得到复杂的耦合代码,因为每个人都使用他们想要的任何功能和数据。类提供权限控制和内在功能,以增强解耦和重用代码。
如果您阅读一些软件工程原理,您会发现大多数标准在没有类的情况下都无法轻松实现。例如:http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29
顺便说一句,当结构分配大量内存并包含多个变量时,值类型变量表示值嵌入到分配结构的位置。相反,引用类型变量的值是外部的,并由指针引用,该指针也嵌入在分配结构的位置中。
您可能会考虑将此作为何时使用 struct 或 class 的指南, https://msdn.microsoft.com/en-us/library/ms229017%28v=vs.110%29.aspx .
√如果类型的实例很小且通常短寿命或通常嵌入其他对象中,则考虑定义结构而不是类。
x避免定义结构,除非类型具有以下所有特征:
从逻辑上讲,它代表一个单个值,类似于原始类型(INT,Double等)。
它的实例大小低于16个字节。
它是不可改变的。
它不必经常装箱。
和...之间的不同 结构体 和 班级 C++ 中的关键字是,当特定复合数据类型没有特定说明符时,则默认情况下 结构体 或者 联盟 public 关键字仅考虑数据隐藏,而 class 是 private 关键字,考虑程序代码或数据的隐藏。总是有一些程序员使用 结构体 对于数据和 班级 为了代码的缘故。欲了解更多信息,请联系其他来源。
出于所有这些因素,可以得出结论,概念类非常适合表示现实世界的对象,而不是“结构”。很大程度上是因为类中使用的 OOP 概念在解释现实世界场景时非常实用,因此更容易将它们融合到现实中。举个例子,默认继承对于结构来说是公共的,但是如果我们在现实世界中应用这个规则,那就很荒谬了。但是在类中默认继承是私有的,这更现实。
无论如何,我需要证明的是类是一个更广泛的、现实世界适用的概念,而结构是一个内部组织较差的原始概念(尽管结构遵循 OOP 概念,但它们的含义很差)
oops 中结构体和类关键字的主要区别在于,结构体中不存在公共和私有成员声明。数据成员和成员函数可以定义为公共、私有和受保护。
我发现了另一个不同之处。如果您没有在类中定义构造函数,编译器将定义一个。但在结构体中,如果没有定义构造函数,编译器也不会定义构造函数。因此,在某些情况下,我们确实不需要构造函数,struct 是更好的选择(性能提示)。抱歉我的英语不好。
类是引用类型,结构是值类型。
当我说类是引用类型时,
基本上它们将包含实例变量的地址。
例如:
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.
}
在主要方法中,
我可以使用 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
- 我的类对象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 进行什么更改,都不会影响 MyStructrue 类型的另一个变量 _myStructObject2。
这就是为什么我们说结构是值类型。
因此,类的直接基类是 Object,结构的直接基类是继承自 Object 的 ValueType。
类将支持继承,而结构则不支持。
我们怎么说呢?
这背后的原因是什么?
答案是类。
它可以是抽象的、密封的、静态的和部分的,并且不能是私有的、受保护的和受保护的内部的。
结构体和类之间的主要区别在于,在结构体中只能声明不同数据类型的数据变量,而在类中可以声明数据变量、成员函数,因此可以通过函数操作数据变量。
-> 我在类与结构中发现的另一个方便的事情是,在程序中实现文件时,如果您想在每组新操作上一次又一次地对结构进行某些操作,您需要创建一个单独的函数,并且需要从文件中读取结构体后传递该结构体对象,以便对其进行一些操作。在课堂上,如果您创建一个函数,每次都对所需的数据执行一些操作..它很容易,您只需从文件中读取对象并调用该函数..
但这取决于程序员他/她认为合适的方式...根据我的说法,我每次都更喜欢类,只是因为它支持 OOP,这就是它在几乎所有语言中实现的原因,并且它是所有时间编程的美妙功能;- )
是的,我忘记提到的最令人难忘的区别是类支持数据隐藏,并且还支持对内置数据类型执行的操作,而结构则不支持!
**更新:** 请忽略此回复。我没有考虑到该结构体的值未初始化但恰好为 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 未初始化。因此,默认构造函数对于 struct 和 struct 的作用似乎确实存在差异。班级。我在 Visual Studio 中看到了这一点。
结构和类之间有3个基本区别
1st- 内存是为堆栈内存中的结构保留的(与编程语言很接近),无论堆栈内存中的类是否仅为引用而保留,而实际内存则在堆内存中保留。
2Nd - 默认情况下,结构是否视为 public ,而类是否视为 private 。
3Rd-不能在结构中重用代码,但在类中我们可以多次重用相同的代码,称为继承