c++primer类详解

news2026/4/30 7:22:15
类的基本思想是数据抽象和封装。数据抽象是依赖接口和实现分离的编程技术。1. 定义抽象数据类型1.1 设计Sales_data类成员函数的声明必须在类内部定义可以在内部或外部作为接口的非成员函数如print、read声明定义都在类的外部。定义在类内部的函数都是隐式的inline函数调用一个成员函数时隐式初始化this指针任何自定义名为this的参数或者变量都是非法的const成员函数const成员函数在参数列表后加上const关键字的函数const的作用是修改隐式this指针的类型默认情况下this的类型是指向类型非常量的常量指针。因此不能将this绑定在一个非常量对象上(不能把this绑定到其他对象)所以也不能在常量对象上调用普通成员函数不能用const 对象访问普通成员函数。const成员函数提高了函数灵活性常量对象以及常量对象的引用或指针只能调用常量成员函数。编译器分两步处理类。1.编译成员声明。2.所有成员声明编译完后编译成员函数体。因此成员声明出现在成员函数体后编译器也可以正常编译在类外定义函数体需要在函数名前加上类名::在类名之后剩余的代码位于作用域之内若返回类型也是在类内声明的就需要在函数名和返回类型前都加上类名::。若在类内声明成了const成员函数在外部定义时const关键字也不能省略。若需要返回类本身使用return *this1.2 定义类相关的非成员函数类相关非成员函数属于类的接口但是不属于类本身。通常把函数声明和定义分开。和类声明在同一头文件内。通常情况下拷贝一个类其实是拷贝其成员。若想拷贝执行其他操作查阅拷贝赋值函数12Sale_data s1;Sale_data s2s1;//s2拷贝了s1的成员1.3构造函数构造函数的任务是初始化类对象的数据成员只要类对象被创建一定会执行构造函数构造函数名与类名相同并且没有返回类型其他与普通函数相同。构造函数不能声明成const默认构造函数默认构造函数无需任何实参若没有为类显式定义任何构造函数编译器隐式构造一个合成的默认构造函数。合成的默认构造函数按照如下规则初始化类成员若存在类内初始值用它来初始化成员否则默认初始化成员某些类不能依赖合成的默认构造函数若类包含内置类型或复合类型成员只有当这些值全被赋予了类内初始值时这个类才适合使用合成的默认构造函数。若类a包含一个成员类b若b没有默认构造函数则编译器无法为a构造正确的默认构造函数若定义了其他构造函数则编译器不会构造默认初始函数1234567classA{//定义了一个实参为string的构造函数//此时编译器不会合成默认构造函数A(std::string a){}}A a;//错误没有默认构造函数A a1(std::string(小黑));//只能用string参数参数列表后加上 defualt表示要求编译器生成默认构造函数defualt可以和声明一起出现在类内也可以作为定义出现在类外。若在类内部则默认构造函数时内联的若在类外部默认不是内联的。1234classA{A()defualt;}A a;//正确编译器生成默认构造函数构造函数初始值列表存在编译器不支持类内初始值这样的话默认构造函数不适用因为默认构造函数使用类内初始值初始化类成员这时应该使用构造函数初始值列表。函数初始值列表是参数列表如下所示冒号以及冒号和花括号间的代码::bookNo(s)构造函数不应该轻易覆盖掉类内初始值除非新赋的值与原值不同在构造函数的过程中没有出现在函数初始化列表中的成员将被执行默认初始化1234567classSales_data{Sales_data(conststd::string s,unsigned n,doublep):bookNo(s),units_sold(n),revenue(p*n){}//当编译器不支持类内初始值时可用如下方法定义Sales_data(conststd::string s):bookNo(s),units_sold(0),revenue(0){}}在类外部定义构造函数,要声明是哪个类的构造函数在函数名前加上类名::123Sales_data::Sales_data(std::istream cin){read(cin,*this);}1.4 拷贝、赋值和析构编译器会为类合成拷贝、赋值和销毁操作。编译器生成的版本对对象的每个成员执行拷贝、赋值和销毁操作2 访问控制和封装访问说明符public说明符后的成员在整个程序内可以被访问private说明符后的成员可以被类的成员函数访问一个类可以包含0个或多个访问说明符有效范围到下一个说明符出现为止。class和struct关键字定义类的唯一区别是class在第一个访问说明符出现之前的区域默认是privatestruct在第一个访问说明符出现之前的区域默认是public2.1 友元类可以允许其他类或函数访问他的非公有成员。方法是用关键字friend声明友元。友元的声明只能在类内部友元声明的位置不限最好在类定义开始或结束前集中声明友元。封装的好处确保用户代码不会无意间破坏封装对象的状态被封装的类的具体实现细节可以随时改变友元在类内的声明仅仅指定了访问权限并不是一个通常意义的函数声明若希望类的用户能够调用某个友元函数需要在友元声明之外再专门对函数进行一次声明为了使友元对类用户可见友元声明与类本身防止在同一个头文件中一些编译器强制限定友元函数必须在使用之前在类的外部声明2.2 类的其他特性接下来介绍类型成员、类的成员的类内初始值、可变数据成员、内联成员函数、从成员函数返回*this、如何定义使用类类型、友元类2.2.1 类成员再探类别名类型成员在类中定义的类型名字和其他成员一样存在访问限制可以是public或者private类别名必须先定义后使用回忆类成员变量可以在类成员函数之后定义但是在类函数中使用原因是编译器先编译类成员变量后边一类成员函数类型成员通常出现在类开始的地方12345classScreen{public://等价于 using pos std::string::size_typetypedefstd::string::size_type pos;}令成员作为内联函数定义在类内部的函数是自动inline的定义在类外部的函数若需要声明内联函数要加上inline;inline成员函数也应该和相应的类定义在同一个头文件夹123456inlineScreen Screen::move(pos r,pos c){pos row r*width;cursor row c;return*this;}可变数据成员永远不会是const即使他是const对象的成员12345678classScreen{publicvoidsome_member()const;private:mutablesize_taccess_ctr;//使用mutable声明可变数据成员}voidScreen::some_member()const{access_ctr;//即使在const成员函数中仍然可以修改可变数据成员}类内初始值使用的初始化形式或者花括号括起来的直接初始化形式2.2.2 返回*this的成员函数注意返回类型是否是引用。是否是引用对函数的使用方法影响很大123456789101112inlineScreen Screen::set(charch){content[cursor] ch;return*this;}inlineScreen Screen ::move(pos r,pos col){cursor r * width col ;return*this;}Screen s(3,2,);//move函数返回s本身所以可以接着调用set函数//并且move函数返回的是Screen的引用若返回的不是引用则会返回一个新的Screen对象s.move(3,2).set(!);从const函数返回的是常量引用在const函数中无法修改类成员变量使用const函数进行重载编写函数display打印Screen中的contents因为只是展示不需要修改值所以这应该是一个const函数。但是希望实现在展示后能移动光标s.display().move(2,3)。这要求display返回的值是可以修改的所以这不应该是const函数。基于const重载可以根据Screen对象是否是const来进行重载。建议多使用do_display这类函数完成实际工作使公共代码使用私有函数可以集中修改没有额外开销123456789101112131415161718192021classScreen{public:Screen* display(std::ostream os){do_display(os);return*this;}constScreen* display(std::ostream os)const{do_display(os);return*this;}private:voiddo_display(std::ostream os)const{oscontent;}}intmain(){constScreen cs(3,3,!);Screen s(3,3,.)cs.display();//因为cs是const的调用第二个const函数s.display();//调用第一个非const的函数}2.2.3 类类型每个类定义了唯一的类型即使成员完全相同也是不一样的类。12345678classA{intmember;}classB{intmember;}A a;B b a;//错误不完全类型类似于函数类也可以只声明不定义,这被叫做不完全类型不完全类型是向程序说明这是一个类名不完全类型使用环境很有限只是可以定义指向这种类型的指针或引用声明但不能定义以不完全类型作为参数或返回类型的函数。类在创建前必须被定义类的成员不能有类本身除了后面介绍的static类但是可以是指向自身的引用或指针2.2.4 友元再探一个类制定了其友元类则友元函数可以访问该类的所有成员友元关系不存在传递性每个类自己负责控制自己的友元类或友元函数定义友元函数的顺序有一个screen类有私有成员content有clear函数可以清除content的内容。1.先声明clear函数2.在screen类中将clear函数函数定义为友元函数3.定义clear函数使用screen类定义友元类有类windowwindow有私有成员content友元类 window_mgr需要直接操作content。正常编写window类在window类中声明friend class window_mgr正常编写 window_mgr类可以直接使用window的content注意将类写在头文件中要按照如下格式否则编译会报错重复的类定义1234#ifndef xxx_H#define xxx_H/class定义///#endif一个类想把一组重载函数定义为它的友元需要对这组函数中的每一个进行友元声明。友元声明仅仅表示对友元关系的声明但并不表示友元这个函数本身的声明12345678910structX{friendviod f(){/*友元函数可以定义在类的内部但是我认为这样没有意义*/X(){f();}//错误f还没有被定义voidg();voidh();}voidX::g(){returnf();}//错误f还没有被定义voidf();voidX::h(){returnf();}//正确f的声明已经在定义中了};2.4 类的作用域定义在类外的方法需要在方法名前使用::说明该方法属于哪一个类在说明属于的类后该函数的作用域位于该类内。即返回类型使用的名字位于类的作用域之外。若返回类型也是类的成员需要在返回类型前使用::指明返回类型属于的类12345//pos的类型声明在window类中并且返回类型在类的作用域外因此要使用window::poswindow::pos window::get_pos(){//在window::get_pos后的所有代码作用域在类内所以返回cursor相当于this-cursorreturncursor;}2.4.1 名字查找和类的作用域类的定义分两步处理1.编译成员的声明2.直到类成员全部可见后编译函数体一般来说内层作用域可以重新定义外层作用域名字但在类中若使用了某个外层作用域中的名字并且该名字表示一种类型则类不能在之后重新定义该名字

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2568064.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…