C++从0到1
文章平均质量分 52
C++个人学习笔记
吴一吴
微秃
展开
-
函数模板高级
是一个左值(能取地址)(要排除第一种情况)、或者用括号括起来的标识符,那么。标准对函数返回类型推导规则做了优化,函数的返回值可以用。函数调用也一种表达式,因此不必担心在使用。的类型与函数的返回值类型相同(函数不能返回。新增的角色), 为函数返回值占了一个位置。分析表达式并得到它的类型,不会计算执行。是一个没有用括号括起来的标识符,则。的类型与该标识符的类型相同,包括。将返回类型移到了函数声明的后面。)如果上面的条件都不满足,则。)C++14的auto关键字。是一个占位符(C++11给。,不必尾随返回类型。原创 2024-06-06 10:35:05 · 72 阅读 · 0 评论 -
函数模板的具体化
可以提供一个具体化的函数定义,当编译器找到与函数调用匹配的具体化定义时,将使用该定义,不再寻找模板。具体化(特例化、特化)的语法:函数模板名(参数列表)函数模板名 (参数列表)//函数体。对于给定的函数名,可以有普通函数、函数模板和具体化的函数模板,以及它们的重载版本。编译器使用各种函数的规则:1)具体化优先于常规模板,普通函数优先于具体化和常规模板。2)如果希望使用函数模板,可以用空模板参数强制使用函数模板。3)如果函数模板能产生更好的匹配,将优先于普通函数。原创 2024-06-06 09:40:29 · 149 阅读 · 0 评论 -
函数模板的注意事项
这个示例代码展示了如何创建模板类及其成员函数、函数模板的使用和重载,以及多个通用数据类型参数的处理。)使用函数模板时,如果是自动类型推导,不会发生隐式类型转换,如果显式指定了函数模板的数据类型,可以发生隐式类型转换。)使用函数模板时,必须明确数据类型,确保实参与函数模板能匹配上。)使用函数模板时,推导的数据类型必须适应函数模板中的代码。)可以为类的成员函数创建模板,但不能是虚函数和析构函数。)函数模板支持重载,可以有非通用数据类型的参数。)函数模板支持多个通用数据类型的参数。原创 2024-06-05 19:02:42 · 115 阅读 · 0 评论 -
函数模板的基本概念
函数模板是通用的函数描述,使用任意类型(泛型)来描述函数。编译的时候,编译器推导实参的数据类型,根据实参的数据类型和函数模板,生成该类型的函数定义。生成函数定义的过程被称为实例化。创建交换两个变量的函数模板:T tmp = a;a = b;b = tmp;在C++98添加关键字typename之前,C++使用关键字class来创建模板。如果考虑向后兼容,函数模板应使用typename,而不是class。函数模板实例化可以让编译器自动推导,也可以在调用的代码中显式的指定。原创 2024-06-05 10:03:30 · 69 阅读 · 0 评论 -
自动推导类型auto
在C语言和C++98中,auto关键字用于修饰变量(自动存储的局部变量)。在C++11中,赋予了auto全新的含义,不再用于修饰变量,而是作为一个类型指示符,指示编译器在编译时推导auto声明的变量的数据类型。语法:auto变量名 = 初始值;在Linux平台下,编译需要加-std=c++11参数。注意:1auto声明的变量必须在定义时初始化。2)初始化的右值可以是具体的数值,也可以是表达式和函数的返回值等。3auto不能作为函数的形参类型。4auto。原创 2024-06-05 08:50:31 · 175 阅读 · 0 评论 -
typeid运算符和type_info类
typeid运算符用于获取数据类型的信息。语法一:typeid(数据类型);语法二:typeid(变量名或表达式);typeid运算符返回type_info类(在头文件中定义)的对象的引用。type_info类的实现随编译器而异,但至少有name()成员函数,该函数返回一个字符串,通常是类名。type_info重载了==和!=运算符,用于对类型进行比较。注意:1type_info类的构造函数是private。原创 2024-06-03 09:32:12 · 233 阅读 · 0 评论 -
运行阶段类型识别dynamic_cast
运行阶段类型识别(RTTI RunTime Type Identification)为程序在运行阶段确定对象的类型,。基类指针可以指向派生类对象,如何知道基类指针指向的是哪种派生类的对象呢?(想调用派生类中的非虚函数)。运算符用指向基类的指针来生成派生类的指针,它不能回答“指针指向的是什么类的对象”的问题,但能回答“是否可以安全的将对象的地址赋给特定类的指针”的问题。语法:派生类指针 = dynamic_cast(基类指针);如果转换成功,返回对象的地址,如果失败,返回。原创 2024-05-30 11:21:20 · 234 阅读 · 0 评论 -
纯虚函数和抽象类
在基类中为派生类保留一个函数的名字,以便派生类它进行重定义。类成为一个抽象类,不能被实例化,但可以用于派生类对象的指针和引用。纯虚函数只有函数名、参数和返回值类型,没有函数体,具体实现留给该。有时候,想使一个类成为抽象类,但刚好又没有任何纯虚函数,怎么办?方法很简单:在想要成为抽象类的类中声明一个纯虚析构函数。的类被称为抽象类,不能实例化对象,可以创建指针和引用。派生类必须重定义抽象类中的纯虚函数,否则也属于抽象类。纯虚函数是一种特殊的虚函数,在某些情况下,这样,通过声明纯虚函数,,把它声明为纯虚函数。原创 2024-05-30 10:31:15 · 282 阅读 · 0 评论 -
如何析构派生类
构造函数不能继承,创建派生类对象时,先执行基类构造函数,再执行派生类构造函数。析构函数不能继承,而销毁派生类对象时,先执行派生类析构函数,再执行基类析构函数。派生类的析构函数在执行完后,会自动执行基类的析构函数。如果手工的调用派生类的析构函数,也会自动调用基类的析构函数。析构派生类的要点如下:1)析构派生类对象时,会自动调用基类的析构函数。与构造函数不同的是,在派生类的析构函数中不用显式地调用基类的析构函数,因为每个类只有一个析构函数,编译器知道如何选择,无需程序员干涉。2。原创 2024-05-29 17:37:24 · 225 阅读 · 0 评论 -
C++网络通讯程序
一、网络通讯的流程编写一个简单的C++网络通讯程序,通常涉及到以下几个步骤:创建套接字、绑定、监听、接受连接、发送和接收数据。以下是一个基本的TCP服务器和客户端的例子,演示了如何使用C++进行网络通讯。原创 2024-05-29 16:38:51 · 201 阅读 · 0 评论 -
多态的对象模型
类的普通成员函数的地址是静态的,在编译阶段已指定。如果基类中有虚函数,对象的内存模型中有一个虚函数表,表中存放了基类的函数名和地址。如果派生类中重定义了基类的虚函数,创建派生类对象时,将用派生类的函数取代虚函数表中基类的函数。C++中的多态分为两种:静态多态与动态多态。静态多态:也成为编译时的多态;在编译时期就已经确定要执行了的函数地址了;主要有函数重载和函数模板。原创 2024-05-21 10:39:36 · 179 阅读 · 0 评论 -
多态的基本概念
基类指针只能调用基类的成员函数,不能调用派生类的成员函数。如果在基类的成员函数前加virtual 关键字,把它声明为虚函数,基类指针就可以调用派生类中同名的成员函数,通过派生类中同名的成员函数,就可以访问派生对象的成员变量。有了虚函数,基类指针指向基类对象时就使用基类的成员函数和数据,指向派生类对象时就使用派生类的成员函数和数据,基类指针表现出了多种形式,这种现象称为多态。基类引用也可以使用多态。注意:1)只需要在基类的函数声明中加上virtual关键字,函数定义时不能加。2。原创 2024-05-21 10:20:17 · 266 阅读 · 0 评论 -
继承的特殊关系
C++要求指针和引用类型与赋给的类型匹配,这一规则对继承来说是例外。但是,这种例外只是单向的,不可以将基类对象和地址赋给派生类引用和指针(没有价值,没有讨论的必要)。)可以把派生类对象赋值给基类对象(包括私有成员),但是,会舍弃非基类的成员。)基类指针或引用只能调用基类的方法,不能调用派生类的方法。)基类指针可以在不进行显式转换的情况下指向派生类对象。)基类引用可以在不进行显式转换的情况下引用派生类对象。)如果继承方式是公有的,派生类对象可以使用基类成员。)如果函数的形参是基类,实参可以用派生类。原创 2024-05-21 10:05:28 · 140 阅读 · 0 评论 -
名字遮蔽与类作用域
如果派生类中的成员(包括成员变量和成员函数)和基类中的成员重名,通过派生类对象或者在派生类的成员函数中使用该成员时,将使用派生类新增的成员,而不是基类的。在类的作用域之外,普通的成员只能通过对象(可以是对象本身,也可以是对象指针或对象引用)来访问,静态成员可以通过对象访问,也可以通过类访问。注意:基类的成员函数和派生类的成员函数不会构成重载,如果派生类有同名函数,那么就会遮蔽基类中的所有同名函数。通过这个例子,你可以看到在派生类中重名成员和基类成员之间的关系以及如何访问这些成员。原创 2024-05-21 09:59:19 · 332 阅读 · 0 评论 -
C++继承方式
例如,当继承方式为protected时,那么基类成员在派生类中的访问权限最高也为protected,高于protected的会降级为protected,但低于protected不会升级。注意:using只能改变基类中public和protected成员的访问权限,不能改变private成员的访问权限,因为基类中的private成员在派生类中是不可见的,根本不能使用。也就是说,继承方式中的public、protected、private是用来指明基类成员在派生类中的最高访问权限的。成员不能在派生类中访问。原创 2024-05-16 08:43:57 · 864 阅读 · 0 评论 -
继承的基本概念
当需要创建多个类时,如果它们拥有很多相似的成员变量或成员函数,可以将这些类共同的成员提取出来,定义为基类,然后从基类继承。如果新创建的类与现有的类相似,只是多出若干成员变量或成员函数时,可以使用继承。继承可以理解为一个类从另一个类获取成员变量和成员函数的过程。派生类除了拥有基类的成员,还可以定义新的成员,以增强其功能。被继承的类称为基类或父类,继承的类称为派生类或子类。继承和派生是一个概念,只是站的角度不同。派生类名:[继承方式]基类名。原创 2024-05-15 13:17:44 · 284 阅读 · 0 评论 -
C++转换函数
构造函数只用于从某种类型到类类型的转换,如果要进行相反的转换,可以使用特殊的运算符函数-转换函数。语法:operator数据类型();注意:转换函数必须是类的成员函数;不能指定返回值类型;不能有参数。可以让编译器决定选择转换函数(隐式转换),可以像使用强制类型转换那样使用它们(显式转换)。//隐式转换。//显式转换。//显式转换。如果隐式转换存在二义性,编译器将报错。在C++98中,关键字explicit不能用于转换函数,但C++11消除了这种限制,可以将转换函数声明为显式的。原创 2024-05-11 15:35:11 · 124 阅读 · 0 评论 -
自动类型转换
将构造函数用作自动类型转换函数似乎是一项不错的特性,但有时候会导致意外的类型转换。对于内置类型,如果两种数据类型是兼容的,C++可以自动转换,如果从更大的数转换为更小的数,可能会被截断或损失精度。在实际开发中,如果强调的是构造,建议使用explicit,如果强调的是类型转换,则不使用explicit。在C++中,将一个参数的构造函数用作自动类型转换函数,它是自动进行的,不需要显式的转换。)多个参数的构造函数,除第一个参数外,如果其它参数都有缺省值,也可以作为转换函数。将CGirl对象初始化为int值时。原创 2024-05-09 17:18:08 · 208 阅读 · 0 评论 -
重载赋值运算符
注意,赋值运算符中我们首先检查了自赋值的情况,然后释放了原有的内存,最后根据源对象的状态分配了新的内存并复制了数据。赋值运算和拷贝构造不同:拷贝构造是指原来的对象不存在,用已存在的对象进行构造;赋值运算是指已经存在了两个对象,把其中一个对象的成员变量的值赋给另一个对象的成员变量。对象的赋值运算是用一个已经存在的对象,给另一个已经存在的对象赋值。如果类的定义中没有重载赋值函数,编译器就会提供一个默认赋值函数。如果类中重载了赋值函数,编译器将不提供默认赋值函数。编译器提供的默认赋值函数,是浅拷贝。原创 2024-05-09 10:40:52 · 153 阅读 · 0 评论 -
多进程共享内存
多线程共享进程的地址空间,如果多个线程需要访问同一块内存,用全局变量就可以了。在多进程中,每个进程的地址空间是独立的,不共享的,如果多个进程需要访问同一块内存,不能用全局变量,只能用共享内存。共享内存(Shared Memory)允许多个进程(不要求进程之间有血缘关系)访问同一块内存空间,是多个进程之间共享和传递数据最高效的方式。进程可以将共享内存连接到它们自己的地址空间中,如果某个进程修改了共享内存中的数据,其它的进程读到的数据也会改变。原创 2024-05-04 18:05:24 · 687 阅读 · 0 评论 -
多进程与信号
在多进程的服务程序中,如果子进程收到退出信号,子进程自行退出,如果父进程收到退出信号,则应该先向全部的子进程发送退出信号,然后自己再退出。原创 2024-05-04 13:02:19 · 144 阅读 · 0 评论 -
linux僵尸进程
如果父进程比子进程先退出,子进程将被1号进程托管(这也是一种让程序在后台运行的方法)。如果子进程比父进程先退出,而父进程没有处理子进程退出的信息,那么,子进程将成为僵尸进程。僵尸进程有什么危害?内核为每个子进程保留了一个数据结构,包括进程编号、终止状态、使用CPU时间等。父进程如果处理了子进程退出的信息,内核就会释放这个数据结构,父进程如果没有处理子进程退出的信息,内核就不会释放这个数据结构,子进程的进程编号将一直被占用。原创 2024-05-04 12:42:42 · 697 阅读 · 0 评论 -
linux创建进程
整个linux系统全部的进程是一个树形结构。0号进程(系统进程)是所有进程的祖先,它创建了1号和2号进程。1号进程(systemd)负责执行内核的初始化工作和进行系统配置。2号进程(kthreadd)负责所有内核线程的调度和管理。用pstree命令可以查看进程树(pstree -p进程编号每个进程都有一个非负整数表示的唯一的进程ID。虽然是唯一的,但是进程ID可以复用。当一个进程终止后,其进程ID就成了复用的候选者。Linux。原创 2024-05-04 11:30:55 · 512 阅读 · 0 评论 -
linux中调用可执行程序
Linux提供了system()函数和exec函数族,在C++程序中,可以执行其它的程序(二进制文件、操作系统命令或Shell脚本)。system()函数提供了一种简单的执行程序的方法,把需要执行的程序和参数用一个字符串传给system()函数就行了。函数的声明:system()函数的返回值比较麻烦。1)如果执行的程序不存在,system()函数返回非0;2)如果执行程序成功,并且被执行的程序终止状态是0,system()函数返回0;3。原创 2024-05-03 23:20:08 · 824 阅读 · 0 评论 -
linux进程终止
调用终止函数的顺序与登记时相反。进程退出前的收尾工作。4)最后一个线程从其启动例程(线程主函数)用。表示函数返回,会调用局部对象的析构函数,如果进程被异常终止,终止状态为非0。8)最后一个线程对取消请求做出响应。直接退出,不会执行任何清理工作。的返回值即终止状态,如果没有。,那么该进程的终止状态是0。还会调用全局对象的析构函数。会执行清理工作,然后退出,5)在最后一个线程中调用。正常终止进程的3个函数(函数登记终止函数(最多3。3)在任意函数中调用。7)接收到一个信号;也是进程终止的状态。原创 2024-05-03 21:37:09 · 668 阅读 · 0 评论 -
Linux的信号
当你在程序运行时按下 Ctrl+C 或发送 SIGTERM 信号给进程时,程序会执行定义好的。如果向服务程序发送一个信号,服务程序收到信号后,调用一个函数,在函数中编写善后的代码,程序就可以有计划的退出。服务程序运行在后台,如果想让中止它,杀掉不是个好办法,因为进程被杀的时候,是突然死亡,没有安排善后工作。2)一个自定义的处理信号的函数,函数的形参是信号的编号。B 缺省的动作是忽略此信号,将该信号丢弃,不做处理。如果向服务程序发送0的信号,可以检测程序是否存活。,大部分的信号的默认操作是终止进程。原创 2024-05-03 20:34:46 · 820 阅读 · 0 评论 -
目录和文件的更多操作
/ 在用mknod、 utime 和write 时才会改变。S_ISDIR(st_mode) // 是否为目录。S_ISREG(st_mode) // 是否为。函数用于判断当前用户对目录或文件的存取权限。// I/O 文件系统的I/O 缓冲区大小。函数用于重命名目录或文件,相当于操作系统的。函数用于删除目录或文件,相当于操作系统的。// 文件最近一次被存取或被执行的时间。参数指定目录或文件的详细信息,保存到。// 文件最后一次被修改的时间。返回值:0-成功,-1-失败,函数用于修改目录或文件的时间。原创 2024-05-03 16:20:14 · 994 阅读 · 0 评论 -
Linux的系统错误
手册为准(一般来说,不属于系统调用的函数不会设置errno,属于系统调用的函数才会设置errno)。中声明,用于在控制台显示最近一次系统错误的详细信息,在实际开发中,服务程序在后台运行,通过控制台显示错误信息意义不大。程序中,如果调用了库函数,可以通过函数的返回值判断调用是否成功。在实际开发中,判断函数执行是否成功还得靠函数的返回值,只有在返回值是失败的情况下,才需要关注。的值只有在库函数调用发生错误时才会被设置,当库函数调用成功时,两个库函数,可以查看出错的详细信息。的值不会被修改,不会主动的置为 0。原创 2024-05-03 15:24:57 · 398 阅读 · 0 评论 -
Linux的目录操作
文件的类型,有多种取值,最重要的是8和4,8-常规文件(A regular file);4-子目录(A directory),其它的暂时不关心。// file name文件名,最长255字符。文件存放在目录中,在处理文件之前,必须先知道目录中有哪些文件,所以要获取目录中文件的列表。// linux系统目录的最大长度是255。// offset to this dirent 在目录文件中的偏移。其它-失败(目录不存在或没有权限)。成功-返回目录的地址,失败-返回空地址。结构体的地址,失败-返回空地址。原创 2024-05-03 12:33:20 · 695 阅读 · 1 评论 -
Linux的时间操作
UNIX操作系统根据计算机产生的年代把1970年1月1日作为UNIX的纪元时间,1970年1月1日是时间的中间点,将从1970年1月1日起经过的秒数用一个整数存放。cout原创 2024-05-03 12:11:41 · 998 阅读 · 0 评论 -
gdb调试正在运行中的程序
通过上述步骤,你可以在程序运行中进行动态地调试,这对于理解程序的行为和诊断复杂问题非常有帮助。这种技术特别适用于调试长时间运行或条件难以复制的问题。原创 2024-05-02 19:07:57 · 144 阅读 · 0 评论 -
gdb调试core文件
如果程序在运行的过程中发生了内存泄漏,会被内核强行终止,提示“段错误(吐核)”,内存的状态将保存在core文件中,方便程序员进一步分析。Linux缺省不会生成core文件,需要修改系统参数。调试core文件的步骤如下:1)用ulimit -a查看当前用户的资源限制参数;2)用把改为unlimited;3)运行程序,产生core文件;4)运行gdb程序名core文件名;5)在gdb中,用bt查看函数调用栈。原创 2024-05-02 18:51:02 · 399 阅读 · 0 评论 -
gdb的常用命令
如果程序有问题,不要问别人为什么会这样,而是立即动手调试。如果希望程序可调试,编译时需要加g选项,并且,不能使用O的优化选项。gdb目标程序set args设置程序运行的参数。例如:./demo张三 西施 我是一只傻傻鸟设置参数的方法是:set args张三 西施 我是一只傻傻鸟breakb设置断点,b 20 表示在第20行设置断点,可以设置多个断点。runr开始运行程序, 程序运行到断点的位置会停下来,如果没有遇到断点,程序一直运行下去。nextn。原创 2024-05-02 17:57:49 · 5 阅读 · 0 评论 -
main函数的参数
这个程序会输出程序的名称、命令行参数的个数以及所有的命令行参数。你可以编译并运行这个程序,并通过命令行传递参数来验证。字符串的数组,存放了环境变量,数组的最后一个元素是空。字符串的数组,存放了每个参数的值,包括程序本身。存放了程序参数的个数,包括程序本身。下面是一个简单的C++程序,用于展示。函数的参数,可以省略不写。在程序中,如果不关心。原创 2024-05-02 17:09:26 · 4 阅读 · 0 评论 -
makefile编写
5. 接下来的几行是编译和链接的命令,通过使用 `g++` 命令编译对应的源文件,并指定了包含文件路径 (`$(INCLUDEDIR)`) 和库文件路径 (`$(LIBDIR)`),以及所需要链接的库文件 (`-lpublic -lmyapi`)。3. `all:demo01 demo02 demo03`:声明了一个名为 "all" 的伪目标,它依赖于 demo01、demo02 和 demo03 这三个目标,表示当我们运行 `make all` 时,会依次编译这三个目标。原创 2024-05-02 16:21:50 · 6 阅读 · 0 评论 -
静态库和动态库
在实际开发中,我们把通用的函数和类分文件编写,称之为库。在其它的程序中,可以使用库中的函数和类。一般来说,通用的函数和类不提供源代码文件(安全性、商业机密),而是编译成二进制文件。发布不方便,如果某一个静态库更新了,所有使用它的程序都需要重新编译。库的二进制文件有两种:静态库和动态库。的时候才把动态库的二进制代码载入内存。程序,只需要更新动态库就行了。程序在运行的过程中,需要用到。如果动态库和静态库同时存在。选项 源代码文件名清单。选项 源代码文件名清单。选项 源代码文件名清单。选项 源代码文件名清单。原创 2024-05-02 12:32:19 · 311 阅读 · 0 评论 -
重载下标运算符
如果对象中有数组,重载下标运算符[],操作将像操作普通数组一样方便。下标运算符必须以成员函数的形式进行重载。下标运算符重载函数的语法:返回值类型 &perator[](参数);或者:const返回值类型 &operator[](参数) const;使用第一种声明方式,[]不仅可以访问数组元素,还可以修改数组元素。使用第二种声明方式,[]只能访问而不能修改数组元素。在实际开发中,我们应该同时提供以上两种形式,这样做是为了适应const对象,因为,如果不提供第二种形式,那么将无法访问。原创 2024-04-29 13:46:47 · 239 阅读 · 0 评论 -
重载左移运算符
重载左移运算符(原创 2024-04-29 12:20:50 · 180 阅读 · 0 评论 -
重载关系运算符
重载关系运算符(==、!=、>、>=、原创 2024-04-29 09:46:39 · 200 阅读 · 0 评论 -
运算符重载基础
成员函数版本的重载运算符函数:形参个数比运算符的操作数个数少一个,其中的一个操作数隐式传递了调用对象。)如果运算符重载既可以是成员函数也可以是全局函数,应该优先考虑成员函数,这样更符合运算符重载的初衷。)重载函数的参数列表中至少有一个是用户自定义的类型,防止程序员为内置数据类型重载运算符。非成员函数版本的重载运算符函数:形参个数与运算符的操作数个数相同;运算符重载函数的返回值类型要与运算符本身的含义一致。)重载函数参数列表中的顺序决定了操作数的位置。)重载函数不能违背运算符原来的含义和优先级。原创 2024-04-29 08:54:57 · 254 阅读 · 0 评论