C++理论概念知识
统一声明:
博客转载 声 明 : 本博客部分内容来源于网络、书籍、及各类手册。
内容宗旨为方便查询、总结备份、开源分享。
部分转载内容均有注明出处,如有侵权请联系博客告知并删除,谢谢!
百度云盘提取码:统一提取码:ziyu
个人网站入口:http://www.baiziqing.cn/
0、C++ 概念
c ++ 编译是用 g++ 扩展名是cpp
1、C / C++的差异性
c++是面向对象的语言,C语言是面向过程的语言
1.1、c++ 有更严格的类型检查
1.2、const 修饰一个变量
表示变量永远只读、可以使用,但不能修;
C语言可以通过const指针修改。
1.3、c++ 强制类型转换: int(a); int(a+b)
1.4、变量引用,为已存在的变量取别名
注意:
1、取别名时需要赋值,但不能为常量赋值
2、函数传参也可以使用
3、函数被调用时、才会用性参取别名
补充:
引用必须初始化
引用在初始化后,不可以改变
不能返回局部变量的引用
如果函数做左值,那么必须返回引用
引用的本质在c++内部实现是一个指针常量
1.5、函数重载,对一个函数赋予新的含义
注意:
1、函数名可以相同,参数列表必须不同
2、参数个数不相同
3、参数个数可以相同,但类型必须不同
1.6、c++ 可以带默认参数
1、只能在函数声明时设置默认参数,定义时不能设置
2、默认参数只能从右到左赋值,中间不能跳跃
注意:
1、默认参数结合函数重载,调用时容易产生歧义
2、对引用类型形参赋值时,必须使用已存在的全局变量
3、使用的时候看实参来调用,函数的返回值不可以作为函数重载的条件
1.7、内联函数,只在声明时使用inline说明
注意:
1、频繁使用的函数
2、代码语句少于等于5局
3、代码语句简单,没有控制语句
目的:
1、优点:提升代码运行效率;缺点:目标程序体积较大
1.8、结构体
1、c++ 中为了保护数据的安全性,引入了访问权限限定符。
2、结构体变量初始化、引入了构造函数
3、释放结构体变量占用资源、引入了构造函数
2、内存模型及名字空间
2.1、作用域
描述了一个名字在文件(编译单元)的多大范围可见。
1、c++ 支持三种形式的域
1、局部域
包含在函数定义或者函数块中长线文本部分
2、名字空间域
不包含函数声明或者类定义内的程序文本部分
3、类域
每个类定义都引入了一个独立的类域
2、变量的作用域
1、局部变量
2、全局变量
3、自动变量
4、名字空间作用域
5、类作用域
2.2、连接性,描述名称如何在各个单元中共享
1、外部链接
名称可以在文件间共享
2、内部链接
名称只能在一个文件中函数共享
2.3、动态内存
1、new
在堆区开辟一个空间
2、delete
释放开辟的堆空间
2.4、声明区,潜在的作用域
1、声明区,可以进行声明的区域
namespace MySpace{ //给这片声明区取名字 MySpace
}
2、名字空间
::
3、潜在的作用域
从声明点、到声明区结尾
3、输入输出流
3.1、输出流
输出流 cout << 表达式1 << 表达式2 << ...;
换行:
控制符:endl
换行符:\n
3.1、输入流
输入流 cin >> 变量1 >> 变量2 >> ...;
4、类和对象
4.1、类体中默认权限为:private 私有的
4.2、成员函数在类体之外的定义语法
数据类型 类名::函数名(<参数列表>){函数体}
4.3、成员变量的作用域
整个类的作用域(类域):类的所有成员函数在函数体区域
4.4、 this 指针
类的所有成员函数都有一个特殊的指针 this, 指向 访问当前成员函数的对象
4.5、类
代码角度:用户自定义的数据类型,由class 进行说明
抽象角度:对象的类型,是一批对象的共享和特征,是对象的抽象概括
4.6、对象
代码角度:就是一个变量
抽象角度:具备行为和属性的事物,一切皆为对象,也就是类的具体实列
4.7、OOP思想:面向对象编程的思想
1、抽象:就是声明定义一个类,抽象概括一类对象的公共性质。
数据抽象:设置成员变量
代码抽象:设置成员函数
2、封装:将数据成员和成员函数结合在一起,形成一个整体,就是类体部分。
4.8、如果设计一个类时,没有显示声明会自动生成
- 构造函数
- 析构函数
- 复制构造函数
- 赋值运算符
- 地址运算符
4.9、构造
构造函数的目的: 用来初始化对象
特点:
1、默认构造函数没有显式说明时,会自动生成
2、构造函数没有数据类型,也就是没有返回值
3、构造函数函数函数名 与 类名一致
4、构造函数只能在定义对象时,被系统自动调用
5、构造函数可以重载
6、构造函数可以有默认参数
7、构造函数是类的 特殊成员函数
8、构造函数一般声明在 public 区域,也可以声明在 protected和private 区域形成限制构造
4.10、拷贝构造
1、浅拷贝:
同类型的两个对象的成员指针,指向同一个堆区空间,两成员指针相互干扰
2、深拷贝:
同类型的两个对象的成员指针,指向两个不同的堆区,互不干扰
4.11、析构函数
1、析构函数:作用用来回收对象占用的资源
特点:
1、没有数据类型,也就是没有返回值
2、函数名由 ~类名 构成
3、析构没有参数和返回值,因此不能被重载。
4、对象生命周期结束时,系统自动调用
5、对象指针遇见 delete 时,系统自动调用
2、包含对象成员(另一个类的对象最为改类的成员变量)的类对象的构造顺序;
构造顺序:
先对象成员构造,再对象构造
析构顺序:
先对象析构,再对象成员析构
4.12、this指针
this指针是一个特殊指针,指向类对象自身的首地址。
4.13、static 修饰成员
1、静态成员变量
1、在整个类域都可见,与具体的对象无关,
static 改变了生命周期,可以作用类型的不同对象之间的数据传递。
2、必须在类体之外定义初始化。
2、静态成员函数:
1、声明时必须有 staic 关键字,定义时不能有 static。
2、函数体中不能访问类的非静态成员。因为这里面没有this指针,也是语法规定的。
3、静态修饰对象:就是修饰一个变量,改变声明周期。
4.14、const 修饰成员
1、const 修饰成员变量,表示只读,必须在构造函数 参数初始化列表中赋初值
1、参数初始化列表语法:
类名(<形参列表>):成员变量(形参1),成员变量(形参2)...
{}
说明:
1、程序在执行时,调用构造函数先执行参数初始化列表,然后才执行 构造函数体
2、包含const 成员变量的类的所有构造函数都必须写出参数初始化列表,为只读变量赋初值。
2、const 修饰成员函数
1、声明定义都必须使用 const 关键字
2、表示不能使用该函数修改任何的成员变量,但是可以访问成员变量
3、const 修饰成员对象:
1、表示该对象定义初始化之后,任何属性都不能更改
2、const 修饰的对象不能访问类的非const 成员函数
4.15、友元
友元可以破坏类的隐藏与封装,慎用。
1、友元函数
1、一个友元函数可以是多个类的有元函数,只需要在各个类中分别声明。
2、友元函数: 就是在成员函数声明之前使用 friend 关键字说明,此时该函数就打破类的封装:
1、友元函数不再是类的成员函数,不能通过对象 . 号访问,只能像普通函数调用一样使用
2、友元函数的函数体中,没有类体的访问权限限定,也就是可以直接通过 对象.号 访问非静态成员,可以通过 类名::静态成员
3、友元函数如果没有类类型作为形参,那么必须在类的外部进行定义,否则声明定义都可以在类体中
4、友元函数必须声明在类体中
2、友元类
1、友元关系不能被继承
2、友元关系是单向的,不具有交互性。
3、如果 B 是 A 的友元类,也就是 A 将 B 当成朋友:
那么在 B 类的所有成员函数中将 打破 A 类的权限。
3、有元成员函数
1、B类的成元函数可以是类A的友元。
5、运算符重载
运算符重载:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
不能被重载的运算符
逗号"." ?号表达式"?:" sizeof 作用域"::"
5.1、成员运算符重载函数
函数体中有this指针指向第一个操作数,重载函数的形参个数 = 操作数 - 1;除了b++或b--
5.2、友元运算符重载函数
函数体中没有this指针指向第一个操作数,重载函数的形参个数 = 操作数;除了b++或b--
重载函数的第一个形参,表示第一个操作数
5.3、函数数据类型
1、一般情况下,由返回值决定。
2、返回类的成员变量,并且期望返回之后能改变成员变量的数值,则返回引用类型。
6、模板
6.1、什么是模板
模板:支持参数多态化都工具,让函数或者;类具备通用性。
目的:让程序员编写与类型无关的代码,是泛型编程的基础
分类:
1、函数模板
仅针对函数参数类型,返回值不同,功能相同的函数
template < class形参名, class形参名> 返回类型 函数名(参数列表)
{
函数体
}
2、类模板
类模板针对仅数据成员和成员函数类型不同的
template < class形参名, class形参名,...> class 类名
{
......
}
template <class T, typename B ...>
template: 关键字,说明是一个模板
class T : 定义类型模板形参,class 等价于 typename
T : 类型模板形参,用来替换数据类型
注意:
模板声明和全局只能在全局。
6.2、类型模板参数
成员函数在类模板 类体外定义的基本语法,必须单独使用 template 说明
注意: 作用域访问符前 必须是 类名<类型形参>::
6.3、非类型模板参数
使用非类型模板形参,目的:让模板中的常数具备灵活性。
template <class T, int var> class Demo
{
......
}
6.4、默认模板参数
template <class Tl, class t2=int> class Demo
{
......
}
6.5、友元函数模板
友元函数声明时定义时都需要加模板 template <class B>
7、类继承
7.1、概念
在进行C编程的时候,代码重用的目的就是提高开发效率、减少错误、让大规模代码开发的关注点转到软件结构上。
C++(OOP)的代码重用除了简单层次的提供类库,还提出了更高层次:
类继承( inheritance)、多态( Polymorphism)、泛型编程( Generic Programming),等等
基类:在面向对象设计中,被定义为包含所有实体共性的class类型,被称为“基类”。
继承:就是在一个已存在的类的基础上建立一个新的类。
派生:从已有的类产生一个字类
最远派生类:在派生体系中派生到最下层的类
派生类继承了基类的所有数据成员和成员函数 ***
//派生一个子类,子类继承父类的所有数据成员和成员函数
/*
公有继承:继承过来的成员的 权限不变
*/
子类和基类有相同的成员,要访问基类 同名成员时,必须使用 基类名::成员名
7.2、派生一个类
//默认向上隐式转换,也就是将派生类对象赋值给基类对象时,将派生类类型转换成基类类型,派生类将会丢弃自身的数据部分
//也称为小范围赋值给大范
//向下转换是不被允许的,不允许将大范围赋值给小范围
7.3、派生类的构造和析构
派生类不能继承基类的构造、析构函数
派生类有自己的构造、析构函数
如果基类构造函数有参数,在从派生类的构造函数把参数传递给基类的构造函数
派生类名∷:构造函数名(参数列表):基类名(参数列表)
1、继承时,构造顺序:先基类构造,再派生构造
析构顺序:先派生类析构,再基类构造
2、包含对象成员的派生类和基类构造顺序:
先 基类构造,再对象成员构造,最后派生类构造
3、析构顺序与构造顺序相反
注意:类体中显示说明,带参数的构造函数,那么无参数的默认构造 不会自动生成
1、派生类构造函数参数初始化列表中,隐式调用基类 默认构造(无参数的构造函数)
2、如果基类出现带参数构造函数,必须在派生类的构造函数参数初始化列表中,显示调用 基类带参构造函数
3、如果派生对象成员的构造函数带参数,必须在派生类的构造函数参数初始化列表中,为对象成员这个变量赋初值。
7.4、is-a关系
is-a 一般是继承关系,has-a一般是组合。
is-a 派生类对象也是一个基类对象,基类对象能够做的操作,派生类也可以
has-a 是一种聚合,表示一个类中有另一个类的对象。
7.5、多重继承
多重继承的路径二义性:解决方式,作用域访问符 和 设置虚基类(虚继承(继承时有 virtual)共同的基类叫虚基类)
8、多态
9.1、什么是多态
9.1.1、什么是多态
简单概括:"一个接口,多种方法";
也就是程序在运行时才决定调用的函数,是面向对象编程领域的核心概念。
9.1.2、什么是多态性:
多态性是将接口与实现进行分离;也就是实现以共同的方法,但因个体差异,而采用不同的策略。
9.1.3、面向对象编程(OPP)主要特征:
- 封装:实现实细节隐藏,使代码模块化。
- 继承:扩展已经存在的代码,目的是为了代码重用。
- 多态:目的是为了接口重用。
9.2、虚函数
9.2.1、多态性的实现:虚函数 (virtual function)
简单地说,用 virtual修饰的成员函数,就是虚函数
A、必须是类的成员函数
B、类的静态成员函数不能成员虚函数
C、构造函数不能定义为虚函数,但是析构函数可以定义为虚函数
D、成员函数使用 virtual 关键字,定义时不需要
E、基类有虚函数,那么派生类中的同名函数(函数名相同,参数列表一致,返回值相同)自动成员析构函数
9.3、覆盖、重载及隐藏
9.3.1、成员函数覆盖( override,也称重写)
是指派生类重新定义基类的虚函数,特征如下:
A、不同的作用域(分别位于派生类与基类)
B、函数名字相同
C、参数相同
D、基类函数必须有 virtual关键字,不能有 static
E、返回值相同
F、重写函数的权限访问限定符可以不同
9.3.2、成员函数重载( overload)
是指函数名相同,参数不同(数量、类型、次序),特征如下:
A、相同的范围(在同一个作用域中)
B、函数名字相同
C、参数不同
D、 virtual关键字可有可无
E、返回值可以不同
9.3.3、成员函数隐藏(也称重定义)
A、不在同一个作用域(分别位于派生类与基类)
B、函数名字相同
C、返回值可以不同
D、参数不同。此时,不论有无 virtual关键字,基类的函数将被隐藏(注意与重载的区别)
E、参数相同,但是基类函数没有 virtual关键字。此时,基类的函数被隐藏(注意与覆盖的区别
9.4、动态联编
9.4.1、联编(链接)
就是将模块或者函数起生成可执行代码的处理过程。按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编
9.4.2、静态联编(静态链接)
是指在編译阶段就将函数实现和函数调用关联起来,因此静态联編也叫早绑定,
9.4.3、动态联编(动态链接)
是指在程序执行的时候才将函数实现和函数调用关联,因此也叫运行时绑定或者晚绑定。C+中一般情况下联編也是静态联編,但是
及到多态和虛拟函数就必须要使用动态联編了
9.4.4、重载只是一种语言特性
编译器根据函数不同的参数表,把同分开来,属于静态联编,与多态无关。引用一句 Bruce Ecke的话要犯傻,如果它不是晚绑就不是多态。
9.5、抽象类
9.5.1、抽象基类:
含有纯虚函数的类就是抽象类。
抽象类没有完整的信息,只能是派生类的基类
抽象类不能有实例,不能有静态成员
派生类应该实现抽象类的所有方法
9.6、虚继承
9.6.1、虚析构函数:
C++使用虚拟继承( Virtual Inheritance),解决从不同途径继承来的同名的数据成员在内存中有不同的
拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。
由于指针指向的对象是基类类型,所以 delete销毁对象的时候,并不会调用派生类的析构函数,
这样就造成员对象消耗不完整
如果基类并不需要回收清理什么,那么析构函数就可以是纯虚函数。
9.7、虚析构函数
虚析构函数:解决资源回收不完整问题(基类指针指向堆区的派生类对象的首地址,释放基类指针)
如果基类并不需要回收清理什么,那么析构函数就可以是纯虚函数。
9.8、限制构造函数
一个类的构造函数访问权限不是 public,该类的构造函数就是限制构成函数
9、异常
9.1、什么是异常
- 什么是异常:异常在一种容错机制,是一种错误处理系统。
- 为什么要有异常:保证软件系统运行的稳定性与健状性
- C++的异常处理机制有3部分组成try(检查)→ throw(抛出)> catch(捕获)
try{
//检查语句
if(错误){
throw异常
}
}
catch(异常类型1){
进行异常处理的语句1
}
...
- C++ 中默认每一个函数都会抛出异常,但是不会指定抛出异常类型,
- 所以函数设计者应该在函数声明定义时需要显示说明抛出的异常类型。throw(...)
9.2、使用标准异常
- C++ 中默认每一个函数都会抛出异常,如果要说明该函数不会抛出异常,那么声明和定义时,都用 throw()
- 如果函数说明为 不会抛出异常,那么内部强行抛出异常,会出现终止程序运行
- throw() :是C++ 旧标准的
- noexcept:是C++ 11 标准中的运算符,32位机中编译时,必须使用 -std=c++0x
- int func(int, int)throw();
9.3、自定义异常
- 在设计一个大系统的时候,往往设计者会自定义很多错误,这些错误在标准错 误里面是没有的,那么就需要我们来设计一些异常类
9.4、异常规范
10、转换函数
10.1、什么是转换函数
**11.1.1、C++中,自定义的类型转换成 其他任何一种类型,都采用转换函数,转换函数应该声明在 要转换的类体中**
转换函数的实质:
运算符重载,只是重载的不是内置运算符,而是类名或者基本数据类型
**11.1.2、转换函数语法:**
operator 类型名()
{
实现转换的语句
}
**11.1.3、转换函数的特点:**
(1)转换函数只能是成员函数,无返回值,空参数,有return返回值。
(2)不能转换成 void 数组 函数类型
(3)常定义为 const 形式
10.2、标准转换函数
10.3、自定义转换函数
10.4、慎用转换函数
扫描二维码关注公众号,回复:
14619993 查看本文章
11、智能指针
11.1、什么是智能指针
12.2、shared-ptr
11.3、unique ptr
11.4、weak-ptr
十二、STL
12.1、STL简介
STL的目的是标准化组件,这样就不用重新,可以使用现成。
- 容器( containers )
特殊的数据结构,实现了数组、链表、队列、等等,实质是模板类
- 迭代器( iterators )
一种复杂的指针,可以通过其读写容器中的对象,实质是运算符重载
- 算法( algorithms )
读写容器对象的逻辑算法:排序、遍历、查找、等等,实质是模板函数
- 空间配置器( allocator)
容器的空间配置管理的模板类
- 配接器( adapters )
用来修饰容器、仿函数、迭代器接口
- 仿函数( functors )
类似函数,通过重载()运算符来模拟函数行为的类
12.2、标准容器简介
STL标准模版库是一种泛型编程。
参考链接 ->
12.3、vector
12.4、list
12.5、deque
C++高级开发推荐资料手册!
C++高级开发推荐资料手册!
链接:https://pan.baidu.com/s/1-U_rettuHeSs1pUqaMbRwg
提取码:xxkt