当前位置: 首页 > news >正文

C++ struct 和 Class的区别

C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据类型的数据结构了,它已经获取了太多的功能。

struct能包含成员函数吗? 能!!!
struct能继承吗? 能!!!
struct能实现多态吗? 能!!!

既然这些它都能实现,那它和class还能有什么区别?

1.最本质的区别就是默认的访问控制权限。

#include <iostream>

struct A    
{
  int a;     //数据成员默认访问权限.struct默认是public,class默认是private
};
struct B : A  //默认的继承访问权限.struct默认是public,class默认是private
{
  int b;
};

这个时候B是public继承A的,如果都将上面的struct改成class,那么B是private继承A的。这就是默认的继承访问权限。

当然,到底默认是public继承还是private继承,取决于子类而不是基类。struct可以继承class,同样class也可以继承struct,那么默认的继承访问权限是看子类到底是用的struct还是class。

 

2.C++中的struct是对C中的struct的扩充,既然是扩充,那么它就要兼容过去C中struct应有的所有特性。例如你可以这样写:

struct A //定义一个struct
{
   char c1;
   int n2;
   double db3;
};
A a={'p', 7, 3.1415926}; //定义时直接赋值 

也就是说struct可以在定义的时候用{}赋初值。那么问题来了,class行不行呢?将上面的struct改成class,试试看。报错!噢~于是有人跳出来说,他又找到了一个区别。我们仔细看看,这真的又是一个区别吗? 

你试着向上面的struct中加入一个构造函数(或虚函数),你会发现什么?struct也不能用{}赋初值了
的确,以{}的方式来赋初值,只是用一个初始化列表来对数据进行按顺序的初始化,如上面如果写成A a={'p',7};则c1,n2被初始化,而db3没有。这样简单的copy操作,只能发生在简单的数据结构上,而不应该放在对象上。加入一个构造函数或是一个虚函数会使内部结构发生改变。而使此{}操作不再有效(会产生vptr指针,这也是为什么需要构造函数的原因)。 

事实上,是因为加入这样的函数,使得类的内部结构发生了变化。而加入一个普通的成员函数呢?你会发现{}依旧可用。其实你可以将普通的函数理解成对数据结构的一种算法,这并不打破它数据结构的特性。 

看到这里,我们发现即使是struct想用{}来赋初值,它也必须满足很多的约束条件,这些条件实际上就是让struct更体现出一种数据结构而不是类的特性。 

那为什么我们在上面仅仅将struct改成class,{}就不能用了呢?

其实问题恰巧是我们之前所讲的——访问控制权限!将struct改成class的时候,访问控制由public变为private了,那当然就不能用{}来赋初值了。加上一个public,你会发现,class也是能用{}的,和struct毫无区别!!! 

 

3.但我上面却没有用“唯一”,而是说的“最本质”,那是因为,它们确实还有另一个区别,虽然那个区别我们平时可能很少涉及。

那就是:“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。这一点在Stanley B.Lippman写的Inside the C++ Object Model有过说明。 

 

我依旧强调struct是一种数据结构的实现体,虽然它是可以像class一样的用。我依旧将struct里的变量叫数据,class内的变量叫成员,虽然它们并无区别。
到底是用struct还是class,完全看个人的喜好,你可以将程序里所有的class全部替换成struct,它依旧可以很正常的运行。最好的建议就是:当你觉得你要做的更像是一种数据结构的话,那么用struct,如果你要做的更像是一种对象的话,那么用class。 

从上面的区别,我们可以看出,struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。

转载于:https://www.cnblogs.com/DswCnblog/p/6489858.html

相关文章:

  • 给程序员最好的18个忠告!
  • 重写父类方法
  • 集中化管理平台saltstack--原理及部署
  • Discuz! X2.5RC 全新安装图文教程
  • java 成员变量与局部变量
  • FineReport中如何实现自动滚屏效果
  • Linux如何查看进程、杀死进程、启动进程等常用命令
  • ViewPager结合view无限滑动
  • 30个php操作redis常用方法代码例子
  • 替换值
  • git简易教程
  • java的PDF纵横向打印
  • 微信三方登录相关(Swift)
  • 大数加法模板
  • System类
  • 分享的文章《人生如棋》
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【笔记】你不知道的JS读书笔记——Promise
  • CentOS从零开始部署Nodejs项目
  • ECMAScript入门(七)--Module语法
  • HashMap ConcurrentHashMap
  • java概述
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • SAP云平台里Global Account和Sub Account的关系
  • Theano - 导数
  • Vue 2.3、2.4 知识点小结
  • WePY 在小程序性能调优上做出的探究
  • 观察者模式实现非直接耦合
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 少走弯路,给Java 1~5 年程序员的建议
  • 我从编程教室毕业
  • 详解移动APP与web APP的区别
  • FaaS 的简单实践
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • #Lua:Lua调用C++生成的DLL库
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (10)STL算法之搜索(二) 二分查找
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (windows2012共享文件夹和防火墙设置
  • (二)换源+apt-get基础配置+搜狗拼音
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (转)重识new
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .net mvc 获取url中controller和action
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .net 托管代码与非托管代码
  • .NET框架设计—常被忽视的C#设计技巧