C++中类(class)和结构(struct)的区别 您所在的位置:网站首页 c语言中的class关键字 C++中类(class)和结构(struct)的区别

C++中类(class)和结构(struct)的区别

2023-10-11 21:20| 来源: 网络整理| 查看: 265

类描述看上去很像包含成员函数以及public和private可见性标签的结构声明,实际上,C++对结构进行了扩展,使之具有与类相同的特性。它们之间的唯一区别是:结构的默认访问类型是public,而类的默认访问类型为private。在C++中通常使用类来实现类描述,而把结构限制为只表示纯粹的数据对象(常被称为普通老数据POD(Plain Old Data)结构,)。

C和C++中结构体的不同: C语言中的结构体不能为空,否则会报错C语言中的结构体只涉及到数据结构,而不涉及到算法,也就是说在C中数据结构和算法是分离的。换句话说就是C语言中的结构体只能定义成员变量,但是不能定义成员函数。在C++中既可以定义成员变量又可以定义成员函数, C++中的结构体和类体现了数据结构和算法的结合。虽然C语言的结构体中不能定义成员函数,但是却可以定义函数指针,不过函数指针本质上不是函数而是指针,所以总的来说C语言中的结构体只是一个复杂数据类型 ,只能定义成员变量,不能定义成员函数,不能用于面向对象编程。在 C 中,必须显式使用 struct 关键字来声明结构。 在 c + + 中,不需要在 struct 定义类型后使用关键字。 C++中类和结构 结构是实值类型(Value Types),而类则是引用类型(Reference Types)。结构使用栈存储(Stack Allocation),而类使用堆存储(Heap Allocation)。

概念:class和struct的语法基本相同,从声明到使用,都很相似,但是struct的约束要比class多,理论上,struct能做到的class都能做到,但class能做到的stuct却不一定做的到。 类型:struct是值类型,class是引用类型,因此它们具有所有值类型和引用类型之间的差异。 效率:由于栈的执行效率要比堆的执行效率高,但是栈资源却很有限,不适合处理逻辑复杂的大对象,因此struct常用来处理作为基类型对待的小对象,而class来处理某个商业逻辑。 总结: (1) 在表示诸如点、矩形等主要用来存储数据的轻量级对象时,首选struct。

(2) 在表示数据量大、逻辑复杂的大对象时,首选class。

(3) 在表现抽象和多级别的对象层次时,class是最佳选择

如果用C语言实现一个类似面向对象的类 // 写法一 #include typedef struct Actress { int height; // 身高 int weight; // 体重 int age; // 年龄(注意,这不是数据库,不必一定存储生日) void (*desc)(struct Actress*); } Actress; void profile(Actress* obj) { printf("height:%d weight:%d age:%d\n", obj->height, obj->weight, obj->age); } int main() { Actress a; a.height = 168; a.weight = 50; a.age = 20; a.desc = profile; a.desc(&a); return 0; }

想达到面向对象中数据和操作封装到一起的效果,只能给struct里面添加函数指针,然后给函数指针赋值。在C语言的项目中你很少会看到这种写法,主要原因就是函数指针是有空间成本的。一般会按照如下的方法写:

// 写法二 #include typedef struct Actress { int height; // 身高 int weight; // 体重 int age; // 年龄(注意,这不是数据库,不必一定存储生日) } Actress; void desc(Actress* obj) { printf("height:%d weight:%d age:%d\n", obj->height, obj->weight, obj->age); } int main() { Actress a; a.height = 168; a.weight = 50; a.age = 20; desc(&a); return 0; }:

再看一个普通的C++类:

// 写法二 #include class Actress { public: int height; // 身高 int weight; // 体重 int age; // 年龄(注意,这不是数据库,不必一定存储生日) void desc() { printf("height:%d weight:%d age:%d\n", height, weight, age); } }; int main() { Actress a; a.height = 168; a.weight = 50; a.age = 20; a.desc(); return 0; }

看着像写法一?其实相当于写法二。C++编译器实际会帮你生成一个类似C语言写法二的形式(这也算是C++ zero overhead指导方针的一个体现)。看到这里就明白了:C++中类和操作的封装只是对于程序员而言的。而编译器编译之后其实还是面向过程的代码。编译器帮你给成员函数增加一个额外的类指针参数,运行期间传入对象实际的指针。类的数据(成员变量)和操作(成员函数)其实还是分离的。 每个函数都有地址(指针),不管是全局函数还是成员函数在编译之后几乎类似。

C++结构体和类总结 结构体和类最大的区别就是前者访问控制默认为public,而类的默认访问控制是private。而对于public,private,protected的访问控制都是在编译期间由编译器检查的,编译通过后,程序执行过程中就不存在什么访问限制了。笼统一点讲,它们在底层只是类型名称不同,原理都相同。类与对象,类是一个抽象的概念,而对象则是这个抽象概念里的一个具体实例。(如人–CXX…)类一般由数据成员和函数成员组成,而具体对象大小的计算只看数据成员,函数成员属于执行代码,不属于类对象的数据。除本身外,类中的数据成员可以是任何已知的数据类型。为什么类中不能定义自身的对象呢?因为类在实例化时,必须要知道它的大小,而如果有自身,会形成递归定义,没有出口。但注意自身的指针类型是可以的,因为任何类型的指针大小是已知的。类对象大小一般就是数据成员大小之和,但也有些特殊情况不符合这个公式。(1)空类,至少占1字节大小,而不是不占内存空间,如果不占内存大小,那么空类就无法实例化。但是空类就算没有数据成员,也可以有函数成员的,所以仍然需要实例化,而这个至少会分配1字节空间给空类,就是用于实例化的。(2)字节对齐 (3)静态成员数据,类似局部静态数据,存在域全局,作用域局部,在编译期间就已经初始化,保存在全局数据区中。它的大小不算在类对象里。this指针:使用过程中被编译器给隐藏起来了,它其实就是个指针,保存调用对象的首地址,指向当前调用者对象本身。对象的成员函数形参处隐式的有这个this,其实是在调用成员函数时,编译器做了一个小动作:利用寄存器ecx保存了对象的首地址(this),并以寄存器传参的方式传递到成员函数中。这也是在成员函数中能直接访问成员数据的原因(this->data),也是判断一个函数不是一般函数而是成员函数的依据。对象作为函数参数:这个不像数组做参数只传递首地址,而是将对象的所有数据成员拷贝一份全部传递过去。这个过程其实会调用系统的拷贝构造函数,就是简单的赋值过程(如果自己写了这个函数,会替换系统的),所以对于有动态内存分配的类,使用这种传参,调用系统的拷贝构造函数,会出现一个这样的错误,这种传参其实是实参与形参处的两个对象保存着相同的数据,而形参处对象在函数调用结束就会释放调用对应的析构函数,所以对于实参和参数处的两个对象都指向的动态空间被释放了。这时实参处对象的指针还在,但所指内存已经释放了。所以对于这种需要我们自己定义拷贝构造函数,一般有两种思路:(1)深拷贝数据,即对于指针数据不仅拷贝指针本身而且指针所指数据也同时拷贝(2)设置引用计数。但是对于对象传参我们一般使用指针或引用形式,这样即可以避免上面所说错误,同时效率也更高。对象作为返回值:情况和对象作为函数参数一样。


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有