c++ primer plus二刷(仔细版)(1)

注:本次复习只关注于一些我所认为对自己有价值的东西,特别基础的东西不会写在本篇文章中

  • 第一章 预备知识
  • OOP(object oriented programming)面向对象编程
  • 编译器:源代码->目标代码->连接程序->可执行代码
  • 第二章 开始学习c++
  • main()会被启动代码调用,启动代码是编译器添加到程序中的,通常从main()处开始执行
  • 预处理器:在主编译之前对源文件进行处理:如include
  • 不同形式的头文件对名称空间即using namespace的要求有差别
  • 变量的声明:避免拼写错误
  • 第三章 处理数据
  • 如果想用不同的字符集,可以在前面加上\U或\u
  • wcha_t:宽字符类型,可以表示扩展字符集
  • char16_t,char32_t
  • 第四章 复合类型
  • 数组初始化:int card[4]={1,2,3,4};int card[4]={0}(全赋值为0)
  • cin会遇到空白(空格,制表符,换行符)确定字符串的结束位置
  • cin.getline(name,num):面向行的输入(针对char[])
  • cin.get(name,num)和cin.get()(针对char[])
  • 混合输入数字和面向行的字符串会导致问题
  • getline(cin,str)
  • 共用体union 节约空间
  • 枚举enum
  • 一定要在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的,适当的地址,这是关于使用指针的金科玉律
  • 数组名和数组名的地址在数值上相同,一个是首元素的地址,一个是整个数组的地址,但在指针运算上有差异
  • 第五章 循环和关系表达式
  • for(i=0,j=10;i<j;i++,j–)
  • int * a,b :b是int
  • define和typedef都是处理别名替换,但typedef能处理更复杂的类型别名
  • 第六章 分支语句和逻辑运算符
  • cctype库中的字符函数
  • 第七章 函数
  • 函数原型:描述了函数到编译器的接口
  • 数组做参数(int arr[])或(int * arr)
  • int age = 39 ; const int * pt = &age;在这里面const限定了pt指向的int不能通过*pt改变,并不是说指向的真正是一个常量,而是相对于pt是一个常量,还是可以通过直接修改age来使age的值发生变化
  • 可以将const变量的地址赋给const指针,但不能赋给非const指针
  • int * const pt:指针本身是常量
  • int *pt[4] int pt [][4]
  • 函数指针:允许在不同的时间传递不同的函数的地址
  • double(*pf)(int) double pam(int) -> pf = pam
  • 第八章 函数探幽
  • 内联函数: inline double square(double x) {return x * x ;} 直接替换:将a=square(1.0)替换成a=1.0 * 1.0
  • 引用接近const指针
  • 如果函数调用的参数不是左值或与相应的const引用参数的类型不匹配,则c++将创建类型正确的匿名变量,将函数调用的参数的值传递给改匿名变量,并让参数来引用变量
  • 使用const可以避免无意修改数据;能使函数处理const和非const实参,否则只能接收非const数据;使函数能够正确生成并使用临时变量
  • 默认参数:int harpo(int n, int m = 4 , int j = 5):只能从右向左添加默认参数,调用的时候也不能跳过某一个参数
  • 函数重载的关键是函数的参数列表–也称为函数特征标(function signature),将类型引用和类型看作是一个特征标,即double x 和 double & x 是同一个特征标,返回类型不算特征标,将非const值赋给const变量是合法的,反之是非合法的
  • 注意:对于非引用变量类型来说,形参中有没有const都是一样的,因为它会复制实参到形参中,所以void mys(int a)这里面有没有const都是一样的
  • template或template
  • c++允许将一个结构赋值给另一个结构(struct)
  • 显示具体化:特殊的template;一般先找非模板版本,再找显示具体化版本,再找模板版本;写法:template<>void swap(job & , job &)或template<>void swap(job & , job &)
  • 显示实例化:template void swap)(int,int),让编译器生成一个int型的函数定义(不需要重新写)
  • 编译器选择函数版本的策略:1. 创建候选函数列表 2. 使用候选函数列表创建可行函数列表,这些都是参数数目正确的函数 3. 确定是否有最佳的可行函数
  • 调用的时候可以显示指明模板函数的类型,比如lesser(x,y)
  • decltype(x+y)xpy:让xpy定义成和x+y相同的类型
  • double && r : 可以匹配右值,比如x+y
  • 第九章 内存模型和名称空间
  • 头文件用<>:在存储标准头文件的主机系统的文件系统中查找;使用" "的话会在当前的工作目录或源代码目录中查找
  • 避免多次包含同一个头文件:#ifndef COORDIN_H #define COORDIN_H #endif
  • 链接性(linkage)描述了名称如何在不同单元间共享,链接性为外部的名称可在文件间共享,链接性为内部的名称可以在一个文件中的函数间共享,也有无链接性
  • 全局作用域也叫文件作用域
  • 自动存储持续性:在程序开始执行其所属的函数或代码块时被创建,在执行完函数或代码块时,使用的内存被释放,只在包含他们的函数或代码块中可见
  • 自动变量被存在栈中,参数也被存在栈中
  • 静态变量:编译器将分配固定的内存块来存储所有的静态变量,这些变量在整个程序执行期间一直存在,如果没有显示地初始化静态变量,将被设置为0
  • 函数外int global = 1000 为外部链接性,static int a = 50 为内部链接性 , 函数内static int b = 50为无链接性
  • 定义和声明:变量只能定义一次,如果在另一个文件中使用全局变量的话,需要使用extern int blem这种声明,声明不分配内存空间,定义会分配内存空间
  • 静态外部变量会隐藏常规外部变量(也就是说他俩可以重名)
  • volatile:告诉编译器一个变量是随时可变的(如硬件可以改变某个变量),可以阻止编译器的优化(将变量的值存在寄存器中下次用的时候直接读取)
  • mutable:即使结构或类变量为const,其中某个mutable成员也可被修改
  • 全局const定义就像使用了static一样,为内部链接性
  • 如果希望某个常量的链接性为外部:extern const int a = 1
  • 函数的链接性默认是外部的,在另一个文件需要先用extern void mys(int a)声明后才能使用,想整成内部的可以static void mys(int a)
  • 通常编译器使用三块独立的内存:一块用于静态变量,一块用于自动变量,一块用于动态存储
  • using声明:using JILL::fetch
  • using编译指令:using namespace std
  • 第10章 对象和类
  • OOP:抽象,多态,继承
  • 构造函数是用来构造函数的
  • 显式调用构造函数:stock food = stock(1,2)
  • 隐式调用构造函数:stock food(1,2)
  • 如果没有提供任何构造函数,c++将自动提供默认构造函数
  • 定义默认构造函数的两种方式:1. 给已有的构造函数的所有参数提供默认值:stock(const string & co = “error”,int n = 0,double pr = 0.0) 2.stock()再写定义
  • 析构函数:~stock():主要是为了delete对象new出来的空间,如果没有提供析构函数,c++将提供一个默认构造函数(当对象要消失的时候就会调用析构函数)
  • 如果stock stock1之前已存在,stock1 = stock(1,2)就不是对stock1的初始化,而是通过构造函数创建一个新的临时的对象复制给它的操作
  • const成员函数:void show() const:保证了对象不会被修改
  • return *this返回对象本身 return this 返回this指针
  • 对象数组:stock mystuff[4]
  • 类里面的const int month = 12 ; double cost[month] ; 是不行的,因为类声明只描述了对象的形式,并没有创建对象
  • 如果想用的话需要创建一个枚举,类声明中的枚举的作用域为整个类,而且所有对象的数据成员中都不会有枚举,所以可以enum{month = 12} ; double cost[month] ;在作用域为整个类的代码中遇到它时,编译器将用12替换他(只是创建了符号常量)
  • 或者static const int month = 12 ; double cost[month] ;也行,这样的话month常量会与其他静态变量储存在一起
  • 作用域枚举:目前不是很懂
  • 第11章 使用类
  • 运算符重载:假如a,b,c都是同一个类的不同对象,a=b+c相当于a=b.operator+©
  • Time operator+(const Time & t) const
  • 友元函数:解决a=b2.5可以但a=2.5b不可以的问题:2.75不是对象,编译器不能用成员函数调用来替换该表达式,需要创建一个非成员函数,而且要有访问类中访问成员的权限,所以有了友元函数,friend Time operator*(double m ,const Time &t),友元函数不是成员函数,不能使用成员运算符来调用,两个操作数都按参数传入
  • 状态成员:enum Mode{rect,pol} Mode mode ; 此时这个mode就是个状态成员,它的值可以为rect或者pol
  • 强制类型转换:int * p = 10 不合法,因为数字默认不能直接赋给指针,但int * p = (int *) 10合法,因为给10转成了指针类型
  • stonewt mycat ; mycat = 19.6 ; 这个是隐式转换,调用了stonewt(double);而explicit关键字如explicit stonewt(double a)会关闭隐式转换,只剩下显式转换;构造函数只能将某种类型转换为类类型
  • 转换函数:将类类型转换成某种类型(一种特殊的运算符函数)operator typename();(需要声明在类中,一般要声明成explicit的)
  • 自动应用类型转换遇到多个转换函数时会报错,但如果只有一个转换函数,编译器会接受
  • 第12章 类和动态内存分配
  • 静态类成员:只创建一个静态类变量副本
  • 复制构造函数(参数是对象);复制运算符(类中没定义时会有一个默认的赋值运算符)
  • 静态类成员函数:不能用对象调用,不与特定的对象关联,只能使用静态数据成员
  • 返回对象会调用复制构造函数,而返回对象引用不会
  • 返回const对象可以解决 net = a + b ; 与 a + b = net 都成立的问题,第二种将a+b存为临时变量,又被赋值成net了,之前的临时对象就没了,返回vector const 就能解决这一问题
  • 成员初始化列表:classy::classy(int n , int m) : mem1(n) , mem2(2) (mem1 mem2分别为类的成员)
  • 第13章 类继承
  • class a : public b
  • 派生类对象存储了基类的数据成员
  • 派生类对象可以使用基类的方法
  • 派生类需要自己的构造函数,可以根据需要添加额外的数据成员和成员函数
  • 派生类不能直接访问基类的私有成员,只能通过基类提供的类方法进行访问
  • 派生类的构造函数例子:a::a(unsigned int r , const string& fn , const string& ln,bool ht) : b(fn,ln,ht) (最后这个:是成员初始化列表)
  • 创建派生类对象时,先调用基类构造函数,再调用派生类构造函数,派生类对象过期时,先调用派生类析构函数,再调用基类析构函数
  • 可以将基类指针或引用指向派生类对象,但只能调用基类方法;反过来不行,因为基类对象不支持一些派生类函数
  • 虚函数:可以根据指针或引用指向的对象的类型选择成员函数,而不是根据指针或对象的类型选择
  • 非构造函数不能使用成员初始化列表语法
  • 虚析构函数:确保了正确的析构函数序列被调用
  • 将函数调用解释成执行特定的函数代码块被称为函数名联编(binding),有静态联编和动态联编
  • 向上强制转换被允许:brass指针可以指向brassplus对象;向下强制转换不被允许
  • 编译器对非虚方法进行静态联编,对虚方法使用动态联编
  • 虚函数的原理:每个对象都有一个隐藏成员:虚函数表(vtbl),是一个指针,指向vtbl,存储了每个对象对应的函数地址
  • 一般protected用于函数,不用在数据变量上,要不然容易被派生类整出来的函数更改数据变量的值
  • 抽象类:有纯虚函数,virtual void a() = 0,不能创建对象
  • 当基类和派生类都采用动态内存分配时,派生类的析构函数,复制构造函数,赋值运算符都必须使用相应的基类方法来处理这些基类元素
  • 第14章 c++中的代码重用
  • 将typedef放在类的private中可以让整个类内使用这个别名
  • explicit可以防止单参数构造函数的隐式转换
  • 类中首先被声明的成员会先被初始化
  • 私有继承:基类的接口只能在派生类内部使用,在派生类中不再作为接口出现,会将基类的公有成员和保护成员都变成自己的私有成员
  • 使用包含时将使用对象名来调用方法,使用私有继承时将使用类名和作用域解析符来调用方法
  • 使用私有继承时可以用强制类型转换来访问基类对象
  • 通常应用包含来建立has-a关系,如果新类要访问原有类的保护成员,或重新定义虚函数,则应使用私有继承
  • 保护继承:会将基类的公有成员和保护成员都变成自己的保护成员
  • class a : public b , public c多重继承,如果第二个public没写的话会默认成private
  • 虚基类:使得从多个类(他们的基类相同)派生出的对象只继承一个基类对象,class a : virtual public b
  • c++在基类是虚的时,禁止信息通过中间类自动传递给基类 p558
  • 可以singwait(const worker &wk ,int p = 0 ,int v - sing::other) : worker(wk),wait(wk,p),sing(wk,v)
  • 使用虚基类时,派生类中的名称优先于直接或间接祖先类中的相同名称,比如class B 和class V:virtual public B , class C:public V,直接调用同名方法时,会调用V的方法
  • 模板类:前面加template template 使用时:stack::a()
  • 模板不是定义,是说明了如何生成定义的编译器指令
  • 默认类型模板参数:template<class T1,class T2 = int>class A
  • 模板的具体化:隐式实例化;p582;显示实例化:template class A<string,100>;显示具体化:template<>class A;部分具体化:templateclass A<T ,int >
  • 成员模板:可以将模板类和模板函数作为成员
  • 将模板用作参数p586
  • 模板类和友元p588
  • 第15章 友元,异常和其他
  • 友元类:友元类的所有方法都可以访问原始类的私有成员和保护成员
  • 剩下的内容暂时先略过,以后再看(从15.2嵌套类开始的内容)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值