C++被称为“C with class”,可见在C++中class是多么重要,与class类似的一个结构就是struct了,struct最早是在C语言中出现的,在C++中对struct的功能也进行了扩展。

class :

  • public(公有):在类内外、派生类中都可被访问
  • protected(保护):希望与派生类共享但是不想被公共访问所使用的访问权限。在基类和派生类中(派生类的友元也可以访问)可以被访问,在类外无法访问
  • private(私有):只有在类内可被访问,类外和子类无法访问

注意事项:

  • 成员不写访问属性时,类的默认访问属性为private
  • 与结构体的不同:结构体默认属性为public

下面就来说一说struct和class的区别吧:

1、默认的继承权限

struct默认是公有继承(public),class默认是私有继承(private)

2、关于默认访问权限

class中默认的成员访问权限是private的,而struct中则是public的。

3、关于大括号初始化问题

struct在C语言中:
在C语言中,我们知道struct中是一种数据类型,只能定义数据成员,不能定义函数,这是因为C语言是面向过程的,面向过程认为数据和操作是分开的,所以C语言中的struct可以直接使用大括号对所有数据成员进行初始化
例如:

struct test
{
int a;
int b;
};
//初始化
test A={1,2};//完全可以
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在C++中class和struct的区别:
在C++中对struct的功能进行了扩展,struct可以被继承,可以包含成员函数,也可以实现多态,当用大括号对其进行初始化需要注意:

  • 当struct和class中都定义了构造函数,就不能使用大括号对其进行初始化
  • 若没有定义构造函数,struct可以使用{ }进行初始化,而只有当class的所有数据成员及函数为public时,可以使用{ }进行初始化
  • 所以struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。

struct和class的sizeof

//C语言的struct
struct A{
};
int main(){
printf("%d",sizeof(struct A));
return 0;
}



//C++  class
#include <iostream>
using namespace std;
class A{


};
int main(){
cout << sizeof(class A);
return 0;
}

试一下两个结果有什么不同?为什么不一样呢?

struct为空的结构体 表示占位为0字节,那么class为空的类的sizeof的意义呢:


一个类的实例化对象所占空间的大小?注意不要说类的大小,是类的对象的大小.

首先,类的大小是什么?确切的说,类只是一个类型定义,它是没有大小可言的。用sizeof运算符对一个类型名操作,得到的是具有该类型实体的大小。

 如果 Class A; A obj; 那么sizeof(A)==sizeof(obj) 那么sizeof(A)的大小和成员的大小总和是什么关系呢,很简单,一个对象的大小大于等于所有非静态成员大小的总和。

为什么是大于等于而不是正好相等呢?超出的部分主要有以下两方面:

1) C++对象模型本身 对于具有虚函数的类型来说,需要有一个方法为它的实体提供类型信息(RTTI)和虚函数入口,常见的方法是建立一个虚函数入口表,这个表可为相同类型的对象共享,因此对象中需要有一个指向虚函数表的指针,此外,为了支持RTTI,许多编译器都把该类型信息放在虚函数表中。但是,是否必须采用这种实现方法,C++标准没有规定,但是这几户是主流编译器均采用的一种方案。

2) 编译器优化 因为对于大多数CPU来说,CPU字长的整数倍操作起来更快,因此对于这些成员加起来如果不够这个整数倍,有可能编译器会插入多余的内容凑足这个整数倍,此外,有时候相邻的成员之间也有可能因为这个目的被插入空白,这个叫做“补齐”(padding)。所以,C++标准紧紧规定成员的排列按照类定义的顺序,但是不要求在存储器中是紧密排列的。

基于上述两点,可以说用sizeof对类名操作,得到的结果是该类的对象在存储器中所占据的字节大小,由于静态成员变量不在对象中存储,因此这个结果等于各非静态数据成员(不包括成员函数)的总和加上编译器额外增加的字节。后者依赖于不同的编译器实现,C++标准对此不做任何保证。

C++标准规定类的大小不为0,空类的大小为1,当类不包含虚函数和非静态数据成员时,其对象大小也为1。如果在类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针指向虚函数表VTable,在32位机器上,一个对象会增加4个字节来存储此指针,它是实现面向对象中多态的关键。而虚函数本身和其他成员函数一样,是不占用对象的空间的。我们来看下面一个例子:(此例子在Visual C++编译器中编译运行)

 

#include using namespace std;


class A { };


class B {
char ch;


void func() { }


};


class C {
char ch1; //占用1字节


char ch2; //占用1字节


virtual void func() { }


};


class D {
int in;


virtual void func() { }


};


void main() {
A a;


B b;


C c;


D d;


cout<<sizeof(a)<<endl;//result=1
cout<<sizeof(b)<<endl;//result=1 //对象c扩充为2个字,但是对象b为什么没扩充为1个字呢(空类的对象一个字节,含一个char的类类对象也为一个字节。)?因为B类只有一个成员变量,普通成员函数不占用内存。


cout<<sizeof(c)<<endl;//result=8
//对象c实际上只有6字节有用数据,但是按照上面第二点编译器优化,编译器将此扩展为两个字,即8字节
cout<<sizeof(d)<<endl;//result=8
}