基本区别

struct 由c语言引入。在c语言中,是定义结构化数据的标准选择。其主观上的定义可参考:https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/classes/#vs

c++ 同时支持struct 和 class. 原因之一是c++ 是 c 的超集,涵盖c 已支持的语言要素,将更好的支持向下兼容(原来能够工作的c 源程序移植到c++,可以支付极少甚至0代价)。首先我们来看结构体在C和C++中的区别。

C语言中的结构体

C语言中的结构体不能为空,否则会报错

要求一个结构或联合至少有一个成员

C语言中的结构体只涉及到数据结构,而不涉及到算法.

也就是说在C中数据结构和算法是分离的。换句话说就是C语言中的结构体只能定义成员变量,但是不能定义成员函数。然而在C++中既可以定义成员变量又可以定义成员函数, C++中的结构体和类体现了数据结构和算法的结合。
不过虽然C语言的结构体中不能定义成员函数,但是却可以定义函数指针,不过函数指针本质上不是函数而是指针,所以总的来说C语言中的结构体只是一个复杂数据类型 ,只能定义成员变量,不能定义成员函数,不能用于面向对象编程。来看一个函数指针的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int FuncAdd(int a, int b)  //求和
{
return a + b;
}

struct CTest1
{
int(*Add)(int, int); //函数指针
};

int main()
{
struct CTest1 test;
int AddResult = 0;
test.Add = My_FuncAdd;
AddResult = test.Add(8, 6);
printf("%d", AddResult);
}

C++语言中的结构体

第一种语法表示

1
2
3
4
struct 结构体名称{
   数据类型 member1;
   数据类型 member2;
};

这种方式在声明结构体变量时为:struct 结构体名称 结构体变量名。例如:

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
struct Student{
int sNo;
char name[10];
};
int main(){
struct Student stu;
scanf("%d",&stu.sNo);
scanf("%s",stu.name);
printf("%d\n",stu.sNo);
}

第二种语法表示

1
2
3
4
typedef struct 结构体名称{
   数据类型 member1;
   数据类型 member2;
}结构体名称别名;

这种方式在声明结构体变量时有两种方式。

1
2
第一种:struct 结构体名称 构体变量名
第二种:结构体名称别名 结构体变量名

原因:这里使用了typedef关键字,此关键字的作用就是声明数据类型的别名,方便用户编程,所以这里用了之后,结构体名称别名就相当于struct 结构体名称。在声明结构体变量时,就无需写struct了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
typedef struct Student{
int sNo;
char name[10];
}Stu;
int main(){
struct Student stu; //方式一
Stu stu1; //方式二
scanf("%d",&stu.sNo);
scanf("%s",stu.name);
printf("%d\n",stu.sNo);
scanf("%d",&stu1.sNo);
scanf("%s",stu1.name);
printf("%d\n",stu1.sNo);
}

第三种方式

1
2
3
4
struct 结构体名称{
   数据类型 member1;
   数据类型 member2;
}结构体变量名;

相当于:

1
2
3
4
5
struct 结构体名称{
   数据类型 member1;
   数据类型 member2;
};
struct 结构体名称 结构体变量名;

这种方式既定义了结构体名称,同时声明了一个结构体变量名。在其它地方也可以通过struct 结构体来再次声明其它变量,而第四种方法则不可以。

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
struct Student{
int sNo;
char name[10];
}stu; //此处stu 是变量名
int main(){
scanf("%d",&stu.sNo);
scanf("%s",stu.name);
printf("%d\n",stu.sNo);
}

第四种方式

1
2
3
4
struct {
   数据类型 member1;
   数据类型 member2;
}结构体变量名;

此方式是匿名结构体,在定义时同时声明2个结构体变量,但不能在其它地方声明,因为我们无法得知该结构体的标识符,所以就无法通过标识符来声明变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>
struct {
int sNo;
char name[10];
}stu,stu1; //匿名结构体,同时定义了2个结构体变量
int main(){
scanf("%d",&stu.sNo);
scanf("%s",stu.name);
printf("%d\n",stu.sNo);
scanf("%d",&stu1.sNo);
scanf("%s",stu1.name);
printf("%d\n",stu1.sNo);
}

以上C++的四种方式,是同样适用在C中,是对C++对C的结构体的包容。

struct 和 class的区别

struct 和 class 实际在C++ 中没有什么区别。

struct 仍然可以继承自另一个struct (很少看到有人这么干)。

未见任何文档有描述说struct 比 class 更快。个人感觉既然struct 和 class 在实现上可以互换,也就是说要支持相同的语言级基础设施和复杂度,那么就不应该存在用哪个更快的问题。

Struct Class
字段类型是public, 默认的继承方式也是public 默认字段类型是private, 默认继承方式也是private。
结构体是值类型,它可以包含数据和方法 类是引用类型
结构体是值类型,不要求堆分配
结构体存储自身的数据在结构体中 类存储一个动态对象的引用
结构体通常用于较小的数据结构 通常较大
结构体会影响性能
一个结构体构造函数直接返回结构体值本身(存储在栈的临时位置),该值在必要时被拷贝
对类而言,多个变量可以使用同一个对象的引用
不适用 对类而言,对一个变量的操作可能会影响到相同引用的其它变量
C语言中的结构体不能为空,否则会报错, 但是C++可以

由于struct 和 class 的可替换性,那什么时候用struct,又什么时候用class呢?

答案: 当你需要值语义的时候用 struct,当你需要引用语义的时候就用 class。

值类型 VS 引用类型

这些问题的核心就是数据和数据的存储位置。我们用局部变量、参数、属性和全局变量来存储数据。存储数据有两种最基本的方式。

值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中。

值类型(value type):byte,short,int,long,float,double,decimal,char,bool 和 struct 统称为值类型。值类型变量声明后,不管是否已经赋值,编译器为其分配内存。

ovvknE

引用类型(reference type):class统称为引用类型。

值类型的实例通常是在线程栈上分配的(静态分配),但是在某些情形下可以存储在堆中。引用类型的对象总是在进程堆中分配(动态分配)。

C++ 中结构体的继承关系

对于成员访问权限以及继承方式,struct中是public。而class中默认的是private,class还可以用于表示模板类型,struct则不行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace std{
struct living_habit{ //生活习惯结构体
...
};

struct animal :public living_habit {//动物继承生活习惯结构体
...
};

struct bird :public animal{ //鸟继承动物
...
};

}

另外namespace std{} : 称namespace(命名空间),在声明一个命名空间时,花括号内不仅可以包括变量,而且还可以包括以下类型:

  • 变量(可以带有初始化);
  • 常量;
  • 数(可以是定义或声明);
  • 结构体;
  • 类;
  • 模板;

C++类的定义和实现

定义(默认的是private):

1
2
3
4
5
6
7
8
class 类名  
{
public:
//公共的行为或属性

private:
//公共的行为或属性
};

实现

两种方式:一种类内 实现(setPoint),另外一种是在类内对成员函数进行声明 ,类外实现(setPoint2)

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
38
39
40
#include <iostream>  
using namespace std;
class Point
{
public:
void setPoint(int x, int y) //类内 实现setPoint函数
{
xPos = x;
yPos = y;
}

void setPoint2(int x, int y); //在类内对成员函数进行声明 ,类外实现

void printPoint() //实现printPoint函数
{
cout<< "x = " << xPos << endl;
cout<< "y = " << yPos << endl;
}

private:
int xPos;
int yPos;
};

void Point2::setPoint(int x, int y) //通过作用域操作符 '::' 实现setPoint函数
{
xPos = x;
yPos = y;
}

int main()
{
Point M; //用定义好的类创建一个对象 点M
M.setPoint(10, 20); //设置 M点 的x,y值
//M.setPoint2(10, 20); //设置 M点 的x,y值

M.printPoint(); //输出 M点 的信息

return 0;
}

总结

概念:class和struct的语法基本相同,从声明到使用,都很相似,但是struct的约束要比class多,理论上,struct能做到的class都能做到,但class能做到的stuct却不一定做的到。
类型:struct是值类型,class是引用类型,因此它们具有所有值类型和引用类型之间的差异。
效率:由于堆栈的执行效率要比堆的执行效率高,但是堆栈资源却很有限,不适合处理逻辑复杂的大对象,因此struct常用来处理作为基类型对待的小对象,而class来处理某个商业逻辑。
关系:struct不仅能继承也能被继承 ,而且可以实现接口,不过Class可以完全扩展。内部结构有区别,struct只能添加带参的构造函数,不能使用abstract和protected等修饰符,不能初始化实例字段。