关于OOP:C++中结构和类的区别是什么?

关于OOP:C++中结构和类的区别是什么?

What are the differences between struct and class in C++?

这个问题已经在c/.net的上下文中提出。

现在我想了解C++中结构和类之间的区别。请讨论OO设计中的技术差异以及选择其中一个或另一个的原因。

我将从一个明显的区别开始:

  • 如果不指定public:private:,则结构的成员默认为public;类的成员默认为private。

我确信在C++规范中晦涩难懂的地方还有其他不同之处。


您忘记了类和结构之间的第二个棘手的区别。

标准(在C++ 98到C++ 11中的{112.2):

In absence of an access-specifier
for a base class, public is assumed
when the derived class is declared
struct and private is assumed when the class is declared class.

为了完整性起见,在(11.2)中定义了类和结构之间更为广泛的区别:

Member of a class defined with the
keyword class are private by
default. Members of a class defined
with the keywords struct or union
are public by default.

附加区别:关键字class可以用来声明模板参数,而struct关键字不能这样使用。


引用C++常见问题解答,

[7.8] What's the difference between
the keywords struct and class?

The members and base classes of a
struct are public by default, while in
class, they default to private. Note:
you should make your base classes
explicitly public, private, or
protected, rather than relying on the
defaults.

Struct and class are otherwise
functionally equivalent.

OK, enough of that squeaky clean
techno talk. Emotionally, most
developers make a strong distinction
between a class and a struct. A
struct simply feels like an open pile
of bits with very little in the way of
encapsulation or functionality. A
class feels like a living and
responsible member of society with
intelligent services, a strong
encapsulation barrier, and a well
defined interface. Since that's the
connotation most people already have,
you should probably use the struct
keyword if you have a class that has
very few methods and has public data
(such things do exist in well designed
systems!), but otherwise you should
probably use the class keyword.


记住C++的起源和与C.的兼容性是值得记住的。

C有结构,它没有封装的概念,所以一切都是公共的。

在使用面向对象的方法时,默认为公共的通常被认为是坏主意,所以在制作一种C形式的C,它本身就有利于OOP(您可以在C中做OO,但它对您没有帮助)这是C++中的想法(最初是"C类"),默认情况下让成员私有是有意义的。

另一方面,如果Stroustrup改变了EDCOX1(1)的语义,使得它的成员在默认情况下是私有的,那么它将破坏兼容性(它不再像标准散布的那样是真的,但是所有有效的C程序也是有效的C++程序,这对给出C++的立足点有很大的影响)。

因此,引入了一个新的关键字class,它与结构完全相同,但默认情况下是私有的。

如果C++从零开始,没有历史,那么它可能只有一个这样的关键字。它也可能不会产生影响。

一般来说,人们在做结构在C中的使用方式、公共成员、没有构造器(只要它不在联合中,就可以在结构中有构造器,就像在类中一样,但人们不这样做)、没有虚拟方法等事情时,会倾向于使用结构,因为语言与阅读C的人交流的次数一样多。用代码来指导机器(否则我们会坚持使用汇编和原始的虚拟机操作码),坚持使用它是个好主意。


类的成员在默认情况下是私有的。默认情况下,结构的成员是公共的。除此之外,没有其他区别。另请参阅此问题。


根据Stroustrup的C++编程语言:

Which style you use depends on circumstances and taste. I usually prefer to use struct for classes that have all data public. I think of such classes as"not quite proper types, just data structures."

从功能上讲,除了公共/私人


结构是一种抽象数据类型,它根据结构规范划分给定内存块。结构在文件序列化/反序列化中特别有用,因为结构通常可以逐字写入文件。(即,获取指向结构的指针,使用大小宏计算要复制的字节数,然后将数据移入或移出结构。)

类是一种不同类型的抽象数据类型,它试图确保信息隐藏。在内部,可以有各种加工、方法、温度变量、状态变量。所有这些都用于向希望使用类的任何代码提供一致的API。

实际上,结构是关于数据的,类是关于代码的。

但是,您需要了解这些仅仅是抽象。创建看起来很像类的结构和看起来很像结构的类是完全可能的。事实上,最早的C++编译器仅仅是将C++代码转换成C的预编译器,因此这些抽象对逻辑思维是有益的,不一定是计算机本身的财富。

除了每个类都是不同类型的抽象之外,类还为C代码命名难题提供了解决方案。由于不能使用相同的名称公开多个函数,开发人员使用()模式。例如,mathlibextreme_max()。通过将API分组到类中,可以将类似的函数(这里我们称它们为"方法")分组在一起,并防止在其他类中命名方法。这允许程序员更好地组织代码,并增加代码重用。至少在理论上。


1)类成员默认为私有,结构成员默认为公共。

例如,程序1编译失败,程序2工作正常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 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。在派生类时,默认访问说明符是私有的。

例如,程序3编译失败,程序4工作正常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 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;
}

唯一的区别是类和结构的默认继承,毫无疑问,它们分别是私有的和公共的。


  • 默认情况下,结构的成员是公共的,类的成员是私有的。
  • 来自其他结构或类的结构的默认继承是公共的。来自其他结构或类的类的默认继承是私有的。
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    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。


    不在规范中,不。主要的区别在于程序员在两年内阅读代码时的期望值。结构通常被假定为pod。当您为定义对象以外的目的定义类型时,模板元编程中也使用结构。


    还有一点需要注意,如果您更新了一个旧版应用程序,该应用程序具有使用类的结构,则可能会遇到以下问题:

    旧代码有结构,代码被清除,并改为类。然后一个或两个虚拟函数被添加到新的更新类中。

    当虚函数在类中时,编译器将在内部添加指向类数据的额外指针,以指向函数。

    如果在旧代码中某个地方使用memfill将结构全部清除为零,这将如何破坏旧的遗留代码,这也将增加额外的指针数据。


    另一个主要区别是在模板方面。据我所知,在定义模板而不是结构时,可以使用类。

    1
    2
    template<class T> // OK
    template<struct T> // ERROR, struct not allowed here

    这只是一个惯例。可以创建结构来保存简单的数据,但稍后会随着成员函数和构造函数的添加而演变。另一方面,看到除public之外的任何东西都是不寻常的:结构中的访问。


    ISO IEC 14882-2003

    9 Classes

    §3

    A structure is a class defined with
    the class-key struct; its members
    and base classes (clause 10) are
    public by default (clause 11).


  • 默认情况下,用关键字class定义的类的成员是private。默认情况下,使用关键字structunion定义的类的成员是public

  • 在没有基类访问说明符的情况下,当派生类声明为struct时,假设为public;当类声明为class时,假设为private

  • 您可以声明一个enum class,但不能声明一个enum struct

  • 您可以使用template,但不能使用template

  • 还要注意,C++标准允许您向前声明一个类型作为EDCOX1(2),然后在声明类型时使用EDCOX1(0),反之亦然。另外,std::is_class::valuetrue,因为y是structclass,而falseenum class


    下面是一个很好的解释:http://carcino.gen.nz/tech/cpp/struct_vs_class.php

    So, one more time: in C++, a struct is identical to a class except that the members of a struct have public visibility by default, but the members of a class have private visibility by default.


    其他答案提到了私有/公共默认值(但请注意,结构是类是结构;它们不是两个不同的项,只是定义同一项的两种方法)。

    值得注意的是(特别是因为ASKER很可能使用MSVC++),因为他提到了"非托管"C++,即VisualC++在某个环境下抱怨,如果一个类用EDCOX1(0)来声明,然后用EDCOX1(1)来定义(或者可能是另一种方式),尽管标准说这是完全合法的。


    • . 在类中,默认情况下所有成员都是私有的,但在结构中默认情况下,成员是公共的。

    • 对于结构没有类似构造函数和析构函数的术语,但是对于类编译器,如果不提供,则会创建默认值。

    • 空结构的sizeof为0字节,因为空类的sizeof为1字节,结构的默认访问类型为public。一个结构应该通常用于分组数据。

    • 类的默认访问类型是private,并且继承是私有的。类应用于分组数据和对该数据进行操作的方法。

      简而言之,当目的是将数据分组,并在需要数据抽象时使用类,也许是继承。

      C++中的结构和类是按值传递的,除非显式去引用。在其他语言中,类和结构可能不同的语义-即对象(类的实例)可以被传递通过引用和结构可以通过值传递。注:有与此问题关联的注释。请参阅讨论页添加到对话中。


    虽然其他答案暗示了这一点,但并没有明确提及——结构是C兼容的,这取决于用法;类是不兼容的。

    这意味着,如果要编写一个要与C兼容的头,那么除了struct(在C世界中,struct不能有函数,但可以有函数指针)之外,没有其他选项。


    类只在软件工程的上下文中有意义。在数据结构和算法的上下文中,类和结构没有那么不同。没有任何规则限制必须引用类的成员。

    当用大量没有类的人开发大型项目时,最终可能会得到复杂的耦合代码,因为每个人都使用他们想要的任何函数和数据。类提供了权限控件和固有项,以增强分离和重用代码。

    如果你阅读了一些软件工程原理,你会发现没有类,大多数标准都不容易实现。例如:http://en.wikipedia.org/wiki/solid_u28object-oriented_-design%29

    顺便说一句,当一个结构分配了一小段内存并包含几个变量时,值类型变量表示值被嵌入到结构的分配位置中。相反,引用类型变量的值是外部的,并且由一个指针引用,该指针也嵌入在分配结构的位置。


    您可以将此作为何时使用结构或类的指导原则,https://msdn.microsoft.com/en-us/library/ms229017%28v=vs.110%29.aspx。

    √ CONSIDER defining a struct instead of a class if instances of the
    type are small and commonly short-lived or are commonly embedded in
    other objects.

    X AVOID defining a struct unless the type has all of
    the following characteristics:

    It logically represents a single value,
    similar to primitive types (int, double, etc.).

    It has an instance
    size under 16 bytes.

    It is immutable.

    It will not have to be boxed
    frequently.


    C++中结构和类关键字的区别在于,当没有特定的特定复合数据类型的说明符时,默认结构或联合是只考虑数据隐藏的公共关键字,而类是考虑程序代码或数据隐藏的私有关键字。总是有些程序员为了数据而使用结构,为了代码而使用类。有关更多信息,请联系其他来源。


    在所有这些因素中,可以得出这样的结论:概念类非常适合于表示现实世界的对象,而不是"结构"。这主要是因为类中使用的OOP概念在解释现实世界场景时非常实用,因此更容易将它们合并到现实中。例如,对于结构,默认继承是公共的,但如果我们对现实世界来说,这是荒谬的。但是在一个类中,默认继承是私有的,这更现实。

    总之,我需要证明的是,类是一个更广泛的、现实世界中适用的概念,而结构是一个原始的概念,内部组织很差(尽管结构遵循OOP概念,但它们的含义很差)。


    OOPS中structure和class关键字的主要区别在于,在结构中不存在public和private成员声明,数据成员和成员函数可以定义为public、private和protected。


    结构和类的主要区别在于,在结构中,只能声明不同数据类型的数据变量,而在类中,可以声明数据变量、成员函数,从而可以通过函数操作数据变量。

    ->我在类vs结构中发现的另一个便利之处是,在程序中实现文件时,如果您想对一个结构的每一组新操作进行一次又一次的操作,您需要生成一个单独的函数,并且您需要在从文件中读取结构的对象之后传递它,以便对其进行一些操作。而在类中,如果您使一个函数每次都对所需的数据执行一些操作..很容易,您只需从文件中读取对象并调用该函数即可。

    但这取决于程序员认为合适的方式……根据我的说法,每次我都喜欢类,因为它支持OOPS,这就是它几乎在所有语言中实现的原因,以及它在所有时间编程中的出色功能;-)

    是的,我忘记提到的最不可原谅的区别是,类支持数据隐藏,也支持在结构不支持的情况下对内置数据类型执行的操作!


    类是引用类型,结构是值类型。当我说类是引用类型时,基本上,它们将包含实例变量的地址。

    例如:

    1
    2
    3
    4
    5
    6
    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.
    }

    在主要方法中,我可以使用为这个类分配内存的新操作符创建这个类的实例并将其基地址存储到myClass类型变量(MyClassObject2)中。

    1
    2
    3
    4
    5
    6
    7
    8
    Static Public void Main (string[] arg)
    {
        MyClass _myClassObject1 = new MyClass();
        _myClassObject1.DataMember = 10;

        MyClass _myClassObject2 = _myClassObject1;
        _myClassObject2.DataMember=20;
    }

    在上述程序中,myClass MyClassObject2=MyClassObject1;指令指示MyClass类型的两个变量

  • MyCaseObjuts1
  • MyCaseObjuts2
  • 并将指向相同的内存位置。它基本上将相同的内存位置分配给相同类型的另一个变量。

    因此,如果我们在任何一个对象类型myClass中所做的任何更改都会对另一个对象产生影响因为两者都指向相同的内存位置。

    "_myClassObject1.dataMember=10;"在这一行,对象的两个数据成员都将包含值10。"_myclassobject2.data member=20;"在此行,对象的数据成员都将包含值20。最后,我们通过指针访问对象的数据成员。

    与类不同,结构是值类型。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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和使用"_mystructtobject1.data member=10"将值10分配给结构的数据成员。

    在下一行,我声明另一个类型为mystructure的变量mystructobject2,并将mystructobject1分配给它。在这里,.NET C编译器创建另一个mystructureObject1对象的副本,并将内存位置分配给mystructure变量mystructtobject2。

    因此,无论我们对mystructTobject1做什么更改,都不会对mystructTrue类型的另一个变量mystructTobject2产生影响。这就是为什么我们说结构是价值类型。

    因此,类的直接基类是对象,结构的直接基类是从对象继承的ValueType。类将支持继承,而结构则不支持。

    我们怎么说的?这背后的原因是什么?答案是上课。

    它可以是抽象的、密封的、静态的和局部的,不能是私有的、保护的和内部保护的。


    **更新:**请忽略此回复。我没有考虑结构的值未初始化但恰好是0的可能性。结构和类之间没有初始化差异。

    我看到结构和类之间的另一个不同之处在于默认初始化。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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未初始化。因此,对于结构和类,默认的构造函数所做的似乎确实有所不同。我在Visual Studio中看到了这一点。


    我发现了另一个不同。如果不在类中定义构造函数,编译器将定义一个。但在结构中,如果不定义构造函数,编译器也不会定义构造函数。因此,在某些情况下,我们确实不需要构造函数,结构是更好的选择(性能提示)。为我糟糕的英语感到抱歉。


    结构和阶级有三个基本区别

    第1个内存是为堆栈内存中的结构(接近编程语言)保留的,堆栈内存中的类是否只为reffrence保留,实际内存在堆栈内存中保留。

    第二个-默认情况下,无论类是否视为私有,结构都视为公共。

    第三,不能在结构中重复使用代码,但在类中,我们可以多次重复使用相同的代码,称为inhertence


    推荐阅读