C++类和对象(上):一文搞懂基础定义与核心规则
gitee地址Yu 子淳 (yyyzzzzccc) - Gitee.com目录1、类和对象的定义class1.1什么是类1.2 类定义格式1.3代码示例1.4类的核心组成元素2、类class与结构体struct的关系编辑3、为啥优先使用class4、什么时候反而用 struct5、 访问限定符6、类域作用域与成员访问规则7、实例化8、内存对齐原则9、this指针的讲解1、类和对象的定义class1.1什么是类我们可以把类理解为一张【图纸】把对象理解为根据图纸造出来的【实物】。举个生活最直观的例子- 汽车图纸规定了汽车必须有车轮、颜色、品牌属性可以行驶、刹车、鸣笛行为——这就是类- 特斯拉、比亚迪、丰田的每一台具体汽车按照图纸造出来、有具体参数、可以实际使用的实物——这就是对象简单总结核心关系类是对象的模板对象是类的实例。类只定义「规则和特征」不占用实际内存对象是类的具体化会开辟内存空间承载真实数据。1.2 类定义格式1、class为定义类的关键字Stack为类的名字这里的类的名字不是唯一的可以自定义。{}中为类的主体注意类定义结束时后⾯分号不能省略。类体中内容称为类的成员类中的变量称为类的属性或成员变量; 类中的函数称为类的⽅法或者成员函数。2、 为了区分成员变量⼀般习惯上成员变量会加⼀个特殊标识如成员变量前⾯或者后⾯加_ 或者 m开头注意C中这个并不是强制的只是⼀些惯例具体看公司的要求。3、C中struct也可以定义类C兼容C中struct的⽤法同时struct升级成了类明显的变化是struct中可以定义函数⼀般情况下我们还是推荐⽤class定义类。4、 定义在类⾯的成员函数默认为inline。1.3代码示例这段代码当中student就是一个类它只规定了学生[有什么、能做什么]没有具体的年龄和姓名也没有执行任何操作只是一个套用模板。1.4类的核心组成元素类由属性成员变量和方法成员函数组成属性成员变量代表事物的静态特征、数据信息。比如人的身高年龄等属性是用来存储数据表述[这个事物是什么样子]。方法成员函数代表事物的动态特征功能操作。比如人吃饭睡觉手机拍照联网。方法用来实现逻辑表述[这个事物能做什么]。2、类class与结构体struct的关系学完类的概念与作用后绝大多数 C 初学者都会遇到同一个困惑结构体 struct 看起来和 class 几乎一模一样也能存数据、写函数那它和类到底是什么关系有什么区别本章彻底讲透struct 和 class 的历史关系、底层联系、语法区别、设计定位一次性终结混淆。2.1 二者真实关系struct 是 class 的「前身」1C语言时代的 struct纯数据容器C 语言没有类、没有面向对象。为了把零散变量打包成一个整体C 设计了 struct 只能存变量不能写函数。它的唯一作用聚合一组相关数据。2C 对 struct 进行全面升级C 为了兼容 C 语言保留了 struct并给 struct 新增了全套面向对象能力- 可以写成员函数- 可以有构造、析构函数- 可以继承- 可以多态- 可以封装所以在 C 语法层面struct 和 class 本质是同一个东西。3一句话总结二者关系struct 是 C 中弱化版、兼容版的 class。class 是 C 专门为面向对象设计的、规范化的 struct。它们同源、同结构、同能力只是默认规则、设计语义、使用场景不同。3.2 struct 与 class 的完全相同点重点很多人不知道在 C 中两者语法能力完全一致1. 都可以封装成员变量2. 都可以定义成员函数3. 都拥有构造函数、析构函数4. 都支持继承、派生5. 都支持多态、虚函数6. 都可以实例化对象也就是说你能用 class 写出来的代码100% 可以用 struct 替代编译通过。3.3 struct 与 class 的唯一本质语法区别1成员默认访问权限不同核心差异- class 默认 private私有- struct 默认 public公有3、为啥优先使用class最核心的区别是默认权限不同class的默认成员权限是private(私有)。外部无法直接访问访问成员数据默认被保护。struct的默认成员是public公有所有成员对外完全暴露任何人都可以直接读写数据。4、什么时候反而用 struct这里补充边界场景做到完整认知避免绝对化- 简单数据结构体坐标、点、颜色、报文协议、传输数据等只有成员变量没有业务方法优先用 struct 。- 兼容 C 语言代码老项目、底层驱动、嵌入式代码需要兼容 C 语法时沿用 struct 。5、 访问限定符• C⼀种实现封装的⽅式⽤类将对象的属性与⽅法结合在⼀块让对象更加完善通过访问权限选择性的将其接⼝提供给外部的⽤⼾使⽤。• public修饰的成员在类外可以直接被访问protected和private修饰的成员在类外不能直接被访问protected和private是⼀样的以后继承章节才能体现出他们的区别。• 访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌如果后⾯没有访问限定符作⽤域就到 }即类结束。• class定义成员没有被访问限定符修饰时默认为privatestruct默认为public。• ⼀般成员变量都会被限制为private/protected需要给别⼈使⽤的成员函数会放为public。6、类域作用域与成员访问规则在前面的讲解当中我们知道类是一个封装了数据和函数的独立模块。但是在实际开发当中我们经常遇到一个问题不创建对象能不能直接访问类里面的成员这里就需要用类域并结合成员类型和访问权限来判断。在前面的C基础当中我们直到作用域运算符语法格式为类名成员名。它的作用就是明确告诉编译器我要访问它的这个成员属于那个类的。为啥要创建对象才能访问成员变量呢是因为我们在前面的讲解中我们可以把class student比作【学生档案模板】这些模板上面只写了姓名年龄学号这些字段并没有具体的值。当你创建student s时就相当于打印了一份空白档案为s这个学生分配独立的空间你才可以往里面填写s.age18如果不创建对象就像手中只有一张模板你没法在模板上直接写年龄18---因为模板是通用的不属于任何一个学生。最简陋的说就是你定义的类只是一个模板没有创建空间所以你直接把18这个值赋给age它是没有办法存放的所以需要先创建变量才能存放这个值。7、实例化什么是实例化呢?1、实例化就是用类类型在物理内存中创建对象的过程称为实例化出的对象。2、我们在上面说了类是一个模板需要创建对象才能进行使用一个类可以创建出多个对象。如上面我们在开头也讲了可以把类看作一个设计图纸对象就是根据设计图纸创建出来的一个个房子它们的布局都是一样的。我们写一个以学生为类的模板我们实例化两个对象d1和d2我们想一下我们假如调用50次成员函数就重复50次吗太浪费空间是时间了我们一般把成员函数放一个公共区域这样每次调用直接在公共区域里面去找这样就会很方便我们在这里先不仔细讲解以后再讲。8、内存对齐原则这个我们在之前的文章当中讲解过这里就不仔细讲解了我们再次把定义重复一遍练几道题就过。• 第⼀个成员在与结构体偏移量为0的地址处。• 其他成员变量要对⻬到某个数字对⻬数的整数倍的地址处。• 注意对⻬数 编译器默认的⼀个对⻬数 与 该成员⼤⼩的较⼩值。• VS中默认的对⻬数为8• 结构体总⼤⼩为最⼤对⻬数所有变量类型最⼤者与默认对⻬参数取最⼩的整数倍。• 如果嵌套了结构体的情况嵌套的结构体对⻬到⾃⼰的最⼤对⻬数的整数倍处结构体的整体⼤⼩就是所有最⼤对⻬数含嵌套结构体的对⻬数的整数倍。注意:在类当中我们算内存大小只需要计算成员变量不用算成员函数。如果类当中只有成员函数只有成员变量默认内存大小为1不能为0代表这个类存在过这时C规定。内存大小的计算首先第一个成员放到结构体偏移量为0的地址处它的字节大小是4所以依次放4个字节第二个成员要对齐到对齐数的整数倍的地址处而对齐数编译器默认值和该成员大小的较小值而又因为编译器的默认值是8而这个成员变量的字节大小是1所以对齐数综合下来就是1结构体的总大小最大对齐数所有成员变量的最大值与默认值的最小的整数倍也就是4的整数倍而现在是5所以再填3个字节大小凑到8成为4的倍数。所以总大小是8.而对于这种只有成员函数没有成员变量的类它的内存大小默认是19、this指针的讲解• student类中有 Init 与 Print 两个成员函数函数体中没有关于不同对象的区分那当d1调⽤Init和Print函数时该函数是如何知道应该访问的是d1对象还是d2对象呢那么这⾥就要看到C给了⼀个隐含的this指针解决这⾥的问题• 编译器编译后类的成员函数默认都会在形参第⼀个位置增加⼀个当前类类型的指针叫做this指针。⽐如student类的Init的真实原型为 void Init(student* const this, int age,int height)• 类的成员函数中访问成员变量本质都是通过this指针访问的如Init函数中给_age赋值 this-_ageage;• C规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理)但是可以在函数体内显⽰使⽤this指针。我们可以看到把this指针补上去也可以正常过但是在实参和形参的位置没有显示this指针是因为C规定会处理掉this指针所以这两处没有显示this指针但是在访问成员变量和打印时我们可以把this指针填上去也是可以的。