
C++
读了两遍《C++ Primer》,发现还是要记点笔记,一来加深印象,二来便于后续查看相关知识点。
JiBeon
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
RTTI
RTTI是运行阶段类型识别的简称,旨在为程序在运行阶段确定对象的类型提供一种标准方式。RTTI只适用于包含虚函数的类层次结构,应为只有对于这种类型的类层次结构,才应该将派生对象的地址赋给基类指针。支持RTTI的元素:1. dynamic_cast运算符:dynamic_cast可以在程序运行阶段检测类型转化是否安全。dynamic_cast主要用来执行安全向下转换1,它检查两者是否...原创 2019-06-24 11:05:09 · 268 阅读 · 0 评论 -
exception类
C++语言本身或者标准库抛出的异常都是exception的子类,称为标准异常,在exception头文件中被定义。exception类中有一个名为**what()**的虚函数,它返回一个字符串,该字符串的特征随实现而异。#include<exception>class bad_hmean : public exception{public: const char * wha...转载 2019-06-23 22:54:30 · 374 阅读 · 0 评论 -
异常
异常的基本思想是让一个函数在发现了自己无法处理的错误是抛出一个异常,然后它的调用者能够处理这个问题,将问题检测和问题处理相分离。调用abort()函数abort()函数原型位于头文件cstilib中,它向标准错误流发送程序异常终止消息,然后终止程序。调用abort()时,不进行任何清理工作,直接终止程序。异常机制异常提供了将控制权从程序的一个部分传递到另一个部分的途径。对异常的处...原创 2019-06-23 21:01:23 · 154 阅读 · 0 评论 -
形参与实参
在定义函数时函数名后面括号中的变量名称时**形参*,形参规定了一个函数所接受数据的类型和数量;在调用函数时,函数名后面括号中的参数是实参,实参用于初始化形参。形参只有被调用时才分配内存单元,在调用结束时立即释放所分配的内存单元。形参类型:形参是按值传递时,将实参的值拷贝给形参,形参和实参是两个相互独立的对象,对形参修改不会对实参造成影响;形参按引用传递时,对应的实参被引...原创 2019-07-01 11:00:22 · 290 阅读 · 0 评论 -
C++字符串和C字符串的转换
(1) .data()data()以字符数组的形式返回字符串内容,但并不添加’\0’。(2) .c_str()c_str()返回一个以’\0’结尾的字符数组。string str = "Hello world.";const char * cstr = str.c_str();上例中,改变了str的内容,cstr的内容也会随着改变。可以将数据复制出来解决问题:string str ...原创 2019-07-05 10:42:24 · 600 阅读 · 0 评论 -
智能指针
智能指针是行为类似于指针的类对象,智能指针包含在头文件<memory>中动态内存管理经常出现的问题:忘记释放内存造成内存泄漏;尚有指针引用就释放,造成引用非法内存的指针。智能指针可自动释放所指向的对象。智能指针包括:auto_ptr、unique_ptr、shared_ptrauto_prt:C98++提供,但已被C++11摒弃。unique_ptr:建立所有...原创 2019-06-26 22:24:07 · 153 阅读 · 0 评论 -
字符数组求长度:strlen()、sizeof()
蓝色神秘代码膜拜大佬https://blog.youkuaiyun.com/z_qifa/article/details/77744482strlen()是函数,在运行时才能计算。参数必须是字符型指针(char*),且必须是以’\n’结尾的。当数组名作为参数传入时,实际上数组已经退化为指针了。它的功能是返回字符串的长度(方式是从字符串的第一个地址开始遍历,知道遇到结束字符’\0’),它返回的长度大小不包括...转载 2019-07-01 13:35:42 · 4962 阅读 · 0 评论 -
指针和引用
指针和引用的区别:从本质上看,指针是地址,引用是别名;从现象上看,指针可以在运行时改变其所指向的值,而引用则总是指向在初始化时被指定的对象不能改变;从内存分配看,程序为指针变量分配内存区域,而不为引用分配内存(所以引用申明时必须初始化,指向一个已经存在的对象);对指针的级数没有限制,但是引用只能是一级:int** p1; //合法,指向指针的指针int*& p2; //合法...原创 2019-07-01 15:54:49 · 167 阅读 · 0 评论 -
数组指针和指针数组
数组指针也称为行指针,它是一个指向数组的指针。数组指针只是一个指针变量,可以用来指向二维数组,它占用一个指针的存储空间。int (*p)[n];定义中()优先级高,首先说明p是一个指针,指向一个整型的一维数组。这个一维数组长度是n,也可以说是p的步长:执行p+1时,p要跨过n个整型数据的长度。指针数组是多个指针变量以数组的形式存在内存当中,占用多个指针的内存空间。int *p[n];...原创 2019-07-01 14:55:14 · 154 阅读 · 0 评论 -
总结:十大排序算法
1. 冒泡排序遍历若干次要排序的序列,每次遍历时,都从前往后依次比较相邻的两个数的大小,如果顺序错误就交换位置。这样,一次遍历以后,最大(or最小)的元素就在数列的末尾。采用相同的方法再次遍历,第二大(or小)的元素就被排在最大元素之前。重复此操作,直到整个数列都有序为止。C++实现:void bubble(int vn[], int size) //参数为数组和数组大小{ in...转载 2019-06-25 21:43:51 · 257 阅读 · 0 评论 -
关联容器map的使用
map内部自建一棵红黑树,自动建立Key-Value的一一对应关系。在map中增加和删除节点对迭代器的影响很小:除了操作节点,对其他的节点都没有什么影响。根据Key值快速查找记录,查找的复杂度基本是Log(N)。1. map的插入map的插入有三种方式:1. 用insert函数插入pair数据;2. 用insert函数插入value_type数据;3. 用数组方式插入数据。用inser...原创 2019-07-07 19:56:10 · 236 阅读 · 0 评论 -
线性容器vector的使用
模板类vector是数组的替代品,它是一种动态数组,在内部自动使用new和delete来管理内存(所以也是自由存储区)。与其他标准的顺序容器相比,vector能更有效访问容器内的元素和在末尾添加和删除元素;而在其他位置添加和删除元素,vector则不及其他顺序容器,在迭代器和引用也不比list支持的好。容器的大小和容器的容量是有区别的:大小是指元素的个数,容量是分配的内存大小,容量一般不小于...原创 2019-07-07 17:55:47 · 267 阅读 · 0 评论 -
标准模板库(STL)
STL是一种泛型编程模式,包含一个容器类模板、迭代器类模板、函数对象模板和算法函数模板的集合。原创 2019-06-27 15:09:21 · 158 阅读 · 0 评论 -
几种序列容器
1. vector该模板在vector头文件中声明。vector是数组的一种类表示,它提供了自动内存管理功能,可以动态改变vector对象的长度,并随着元素的添加和删除而增大和缩小。它提供对元素的随机访问。在尾部添加和删除元素的时间是固定的,但在头部或中间插入和删除元素的复杂度为线性时间。2. dequedeque模板类(在deque头文件中声明)表示双端队列,也支持随机访问。与v...原创 2019-06-27 15:32:58 · 312 阅读 · 0 评论 -
关联容器
关联容器是对容器概念的改进,将值和键关联在一起,并使用键来查找值。对于关联容器X,表达式X::value_type指出值类型,X::key_type指出键类型。关联容器的优点在于,它提供了对元素的快速访问。与序列相似,关联容器也允许插入新元素,但不能指定元素的插入位置。STL提供了4中关联容器:set、multiset、map、multimap。set、multiset对于set来说...原创 2019-06-27 16:09:29 · 155 阅读 · 0 评论 -
类模板表示数组中元素数量的两种方式
模板常用作容器类,为容器类提供可重用代码是引入模板的主要动机。允许指定数组大小的方法:在类中使用动态数组和构造函数参数来提供元素数目(如模板类vector)template<class Type>class Stack{private: enum{SIZE = 10}; int stacksize; Type * items;public: explicit ...原创 2019-06-21 22:56:15 · 569 阅读 · 0 评论 -
递归使用模板
对于二位数组定义:ArrayTP< ArrayTP<int,5>, 10 > twodee;使得twodee是一个包含10个元素的数组,其中每个元素都是一个包含5个int元素的数组。与之等价的常规数组声明如下:int twodee[10][5];注意:在模板语法中,维的顺序与等价的二维数组相反。...原创 2019-06-21 23:00:19 · 837 阅读 · 0 评论 -
类模板
模板是一种泛型编程思想,提供参数化类型,即能够将类型名作为参数传递给接收方来建立类或函数(形式、功能相似,类型不同),也是一种实现代码重用的重要方式。类模板定义类模板在class上一行使用template加尖括号声明:template<typename 类型参数1, typename 类型参数2,...>class 类名{...};当模板被调用时,参数类型将被具体的类型...原创 2019-06-21 23:00:35 · 281 阅读 · 0 评论 -
模板的实例化与具体化
实例化:模板本身不会生成函数或类定义,它只是一个用于生成函数或类的方案,编译器使用模板为特定类型生成函数或类定义的过程叫做模板的实例化。具体化:为模板中抽象的泛型指定具体的类型。它包含隐式实例化、显示实例化、显式具体化、部分具体化。隐式实例化:编译器使用通用模板提供的处方生成具体的类定义,声明一个对象,指出所需的类型。编译器生成对象之前,不会生成类的隐式实例化:ArrayTP&...原创 2019-06-22 11:27:12 · 2933 阅读 · 1 评论 -
模板类和友元
模板的友元分3类:非模板友元;约束模板友元,即友元的类型取决于类被实例化时的类型;非约束模板友元:即友元的所有具体化都是类的每一个具体化的友元。非模板友元函数友元函数没有类型参数:template <class T>class HasFriend{public: friend void counts(); ...};上述声明使counts()函数成...原创 2019-06-22 15:32:49 · 1019 阅读 · 0 评论 -
接口和实现
使用公有继承时,类既可以继承接口,也可以继承实现。(例外:纯虚函数只有接口没有实现)。使用组合1时,类可以获得实现,但不能获得接口。组合又称包含、层次化,实现has-a关系,详见 ↩︎...原创 2019-06-20 19:53:07 · 492 阅读 · 0 评论 -
私有继承
实现has-a关系的途径:包含(组合、层次化):类成员本身是另一个类的对象。私有继承。保护继承。私有继承在派生时,使用private关键字而不是public来定义类。class Student:: private string, private valarray<double> {...};使用私有继承,基类的公有成员和保护成员都将称为派生类的私有成员。这意味着基...原创 2019-06-20 22:45:51 · 746 阅读 · 0 评论 -
使用using重新定义访问权限(私有/保护继承)
使用私有or保护继承时,基类的公有成员将成为私有成员or保护成员,不能像公有继承那样,可以直接使用基类方法。要达到这个目的,有两种方法:定义一个使用该基类方法的派生类方法使用using重新定义访问权限。使用一个using声明来指出派生类可以使用特定的基类成员,即使采用的是私有派生。class Student : private string, private valarray<...原创 2019-06-20 23:01:19 · 583 阅读 · 0 评论 -
多重继承与虚基类
MI描述的是有多个直接基类的类。注意:公有继承必须使用关键字public限定每一个基类,因为默认为private。class SingWaiter : public Waiter, public Singer {...};MI面临的问题:从两个不同的基类继承同名的方法;从两个或更多相关基类那里继承同一个类的多个实例。菱形继承问题:当多重继承的两个父类有共同的祖先时,...原创 2019-06-21 17:14:44 · 354 阅读 · 0 评论 -
总结:C++面向对象的三大特性——封装、继承、多态
传统的面向过程编程,数据以及对数据进行操作的函数都是分离的独立个体。OOP提供了将数据和方法整合起来的途径——类和对象。对象是类的实体,使程序更模块化,提升了代码重用水平。封装封装的思想是将内部细节和使用方式分开,把实现的细节隐藏,只暴露公有的接口,实现代码的模块化。C++通过访问标志符(private、protected、public)实现类的封装——将数据声明为private,只能通过...原创 2019-06-19 14:42:37 · 902 阅读 · 0 评论 -
什么不能被继承
构造函数继承意味着派生类对象可以使用基类的方法,然而,构造函数在完成其工作之前,对象并不存在。创建派生类对象时,必须调用派生类的构造函数,派生类的构造函数必须使用成员初始化列表语法来调用基类构造函数,以创建派生对象的基类部分。析构函数在释放对象时,程序首先调用派生类的析构函数,然后调用基类的析构函数。通常,对于基类,其析构函数应设置成虚的。赋值运算符因为派生类继承的方法的特征...原创 2019-06-18 22:01:19 · 433 阅读 · 0 评论 -
继承和动态内存分配
1、派生类不使用new:此时不需要为派生类定义显式析构函数、复制构造函数和赋值运算符。2、派生类使用new:此时需要为派生类定义显式析构函数、复制构造函数和赋值运算符。基类中使用了动态内存分配:class baseDMA{private: char * label; int rating;public: baseDMA(const char * l="null", int r...原创 2019-06-18 21:11:01 · 321 阅读 · 0 评论 -
抽象基类和纯虚函数
纯虚函数在一个虚函数的声明语句后加上=0,就可以将一个虚函数变成纯虚函数。纯虚函数只用声明,而不能在类中定义,但要求任何派生类中都要定义自己的实现方式。其存在就是为了提供接口。抽象基类(ABC)引入原因:为了方便实现多态;有时基类本身生成对象是不合理的。定义:包含纯虚函数的类叫做抽象基类,不能创建该类的对象,只能用作基类。抽象基类不能用作参数类型、函数返回类型。但是可以声明指...原创 2019-06-18 20:32:31 · 209 阅读 · 0 评论 -
动态联编和静态联编
程序调用函数时,将函数调用解释为执行特定的函数代码块被称为函数名联编。在编译过程中进行联编被称为静态联编,又称为早期联编。然而,虚方法使得这项工作变得更困难,使用哪个函数不能在编译时确定,因为编译器不知道用户将选择哪个类型的对象。在程序运行阶段进行联编被称为动态联编,又名晚期联编。编译器对虚方法使用动态联编。...原创 2019-06-18 18:05:33 · 374 阅读 · 0 评论 -
访问控制权限protected
关键字protected与private相似,在类外只能通过公有类成员才能访问。对于派生类:派生类的成员可以直接访问protected成员,但不能直接访问private成员。因此,对外部世界来说,保护成员的行为与私有成员类似;对于派生类来说,保护成员行为与公有成员类似。...转载 2019-06-18 17:21:26 · 274 阅读 · 0 评论 -
虚函数virtual与多态
多态:希望同一个方法在派生类和基类中的行为是不同的,即方法的行为取决于调用该方法的对象。这种行为被称为多态——具有多种形态。实现多态公有继承的两种方式:在派生类中重新定义基类方法。使用虚方法。虚函数virtual虚方法的用途示例假设要创建一个数组来保存基类对象和派生类对象,但数组中所有元素的类型必须是相同的。可以创建指向基类的指针数组,这样,每个元素的类型都相同,但由于使用的...原创 2019-06-18 17:11:15 · 454 阅读 · 0 评论 -
派生类和基类
OOP的主要目的之一是实现代码可重用。类继承从已有的类派生出新的类,而派生类继承了原有类(基类)的数据成员和方法。派生类不能直接访问基类的私有成员,必须通过基类方法进行访问。因此,派生类构造函数必须使用基类构造函数(通过成员初始化列表)。派生类和基类之间的特殊关系派生类对象可以使用基类的方法,条件是方法不是私有的。基类指针可以在不进行显式类型转换的情况下指向派生类对象。基类引用可...原创 2019-06-18 14:40:31 · 1651 阅读 · 0 评论 -
队列的出队、入队
class Queue{private: struct Node { Item item; struct Node * next; }; enum {Q_SIZE = 10}; Node * front; Node * rear; int items; const int qsize; ...};将项目添加到队尾(入队):bool Queue::enqueue(const...转载 2019-06-18 09:35:35 · 4041 阅读 · 0 评论 -
成员初始化列表
成员初始化列表由逗号分隔的初始化列表组成(前面带冒号)。它位于参数列表的右括号之后、函数体左括号之前。这种格式只能用于构造函数。必须用这种格式初始化非静态const数据成员(C++11之前)1;必须用这种格式初始化引用数据成员2。class Agency {...};class Agent{private: Agency & belong; //引用数据成员 ......原创 2019-06-17 21:22:03 · 509 阅读 · 0 评论 -
类中嵌套结构和类
在类声明中声明的结构、类或枚举被称为是被嵌套在类中,其作用域为整个类。这种声明不会创建一个数据对象,而是指定可以在类中使用的类型。如果在private中嵌套,只能在类中使用它。如果在public中嵌套,可以通过类加作用域解析运算符的方式调用。...原创 2019-06-17 21:06:07 · 420 阅读 · 0 评论 -
定位new运算符
定位new运算符使得可以在分配内存时指定内存位置。定位new运算符直接使用传递给它的地址,不负责判断哪些内存单元已被使用,也不查找未使用的内存块。由于本质上定位new运算符并不开辟新的内存,也就不应该用delete释放它。char * buffer = new char[152];JustTest *pc; //假设前面已声明了一个JustTest类pc = new (buffer)...原创 2019-06-17 20:42:08 · 211 阅读 · 0 评论 -
返回对象与引用的说明
如果方法或函数要返回局部变量,则应该返回对象,而不是指向对象的引用,因为在被调用函数执行完毕时,局部对象将调用其析构函数。如果方法或函数要返回一个没有公有复制构造函数的类(如ostream)的对象,必须返回一个指向这种对象的引用。有些方法和函数(如重载的赋值运算符)可以返回对象,也可以返回指向对象的引用。在这种情况下,应首选引用,因为其效率更高。...原创 2019-06-17 20:11:13 · 727 阅读 · 0 评论 -
静态类成员函数
在成员函数的声明前加关键字static,将其声明为静态的。不能通过对象调用静态成员函数,应使用类名和作用域解析运算符来调用它。静态成员函数只能使用静态数据成员,因为静态成员函数不与特定的对象相关联。...原创 2019-06-17 19:25:36 · 322 阅读 · 0 评论 -
复制构造函数和深度复制
浅复制和深度复制浅复制:仅复制指针值,新的指针和原来的指针指向同一地址,执行析构函数会释放同一内存单元两次,造成悬挂指针。深度复制:通过将副本地址赋给新成员,复制指向的数据。复制构造函数如果类中包含了使用new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而仅仅是指针。复制构造函数用于将一个对象复制到新创建的对象中,因此,它用于初始化过程中(包括按值传递参数),而不是...原创 2019-06-17 19:02:01 · 278 阅读 · 0 评论 -
类的自动类型转换和强制类型转换
某种类型转换为类类型定义接受一个参数的构造函数可用来将与该参数相同的类型转换为类类型,如:Stonewt(double lbs);因此,可以这样编写代码:Stonewt myCat;myCat=19.6; //使用Stonewt(double)将19.6转换为Stonewt类型这里,使用构造函数Stonewt(double)创建一个临时的Stonewt对象,并将19.6作为初始化值...原创 2019-06-17 15:56:34 · 669 阅读 · 0 评论