C++基础知识整理

c++面向对象的三大特性

  • 封装;将相同属性的数据和方法封装在一起,加权限区分,用户只能借助公共方法操作私有数据.
  • 继承:体现在类和类之间的关系,如果A类继承B类,那么A类直接拥有B类的数据和方法.
  • 多态:一个接口(函数),多种功能.

作用域运算符::

::解决归属问题(谁是谁的谁)

结构体类型增强

  • c++允许函数作为结构体成员

新增BOOl类型

占1个字节;返回值true或者false;

三目运算符

c++返回的是引用,而c语言返回的是值;

int a=10;
int b=20;
a>b?a:b=10;(c++允许,c语言报错)

左值和右值

左值:能被赋值的值.(在等号的左边)
右值;只能放右边的值.(不能被赋值的值)

const增强

  • 尽量使用const代替#define
  • const有类型,可以进行编译器类型的安全检查.#define无类型,不可以进行类型检查
  • const有作用域,而#define不重视作用域,宏不能作为命名空间,结构体,类的成员,而const可以.

引用

  • 引用的本质:就是给变量名取个别名
  • 引用定义的步骤:
    1.&别名
    2 给哪个变量取别名就定义该变量
    3 从上往下整体替换

内联函数

  • 在编译阶段,将内联函数中的函数体 替换函数调用处.避免函数调用时的开销.
  • 内联函数:必须在定义的时候使用关键字inline修饰,不能在声明的时候使用inline.
  • 宏函数和内联函数的区别:
    同:宏函数和内联函数 都会在适当的位置进行展开,避免函数调用开销
    异: 宏函数的参数没有类型,不能保证参数的完整性.
    内联函数的参数有类型,能保证参数的完整性.
    宏函数在预处理阶段展开
    内联函数在编译阶段展开
    宏函数没有作用域的限制,不能作为命名空间,结构体,类的成员
    内联函数有作用域的限制,能作为命名空间,结构体,类的成员.
  • 内联函数的注意事项

在内联函数定义的时候加inline修饰
类中的成员函数默认都是内联函数(不加inline 也是内联函数)有时候就算加上inline也不一定是内联函数(内联函数条件)
条件:->1.不能存在任何形式的循环语句
2.不能存在过多的条件判断语句函数体不能过于庞大
3.不能对函数取地址
有时候不加inline也可能是内联函数

函数重载

  • 函数重载是c++的多态的特性(静态多态)
  • 函数重载:用同一个函数名,代表不同的函数功能.
  • 函数重载的条件:
    1.同一作用域,函数的参数类型,个数,顺序不同都可以重载
    c++中不能直接将函数名作为函数的入口地址—>函数名和参数共同决定函数的入口地址.

缺省参数

在函数声明处,给函数参数一个默认的值,如果函数调用处,用户没用传实参,编译器就可以使用这个默认的值.
注意:如果函数的某个参数设置为默认参数,那么这个参数的右边的所有参数都必须是默认参数.

  • 类将数据和方法封装在一起,加以权限区分.用户只能通过公共方法访问私有数据.

定义一个类 关键字class

  • 类的权限分为:private,protected,public.但是在类的内部不存在权限之分.只是对类外有效.
  • 如果类不涉及到继承,private,protected没有区别,都是私有属性.
    在这里插入图片描述

构造函数

  • 构造函数:完成对象的初始化,系统自动变量.
  • 析构函数:完成对象的释放,系统自动调用.

构造函数的定义:
构造函数函数名和类名相同,没有返回值类型,连void都不可以,但可以有参数(重载).
先给对象开辟空间(实例化),再调用构造函数(初始化).
构造函数的调用时机:
如果用户不提供任何构造函数,编译器默认提供一个空的无参构造.如果用户定义了>构造函数(不管是有参还是无参),编译器不再提供默认构造函数

析构函数

  • 当对象生命周期结束的时候,系统自动调用析构函数.
  • 函数名和类名称相同,在函数名前加~,没有返回值类型,没有函数形参.(不能被重载).
    先调用析构函数,再释放对象空间.
  • 一般情况下,空的析构函数就足够.但是如果一个类有指针成员,这个类必须写析构函数,释放指针成员所指向空间.

拷贝构造函数

  • 拷贝构造:本质是构造函数
  • 拷贝构造调用时机:旧对象.初始化.新对象,才会调用拷贝构造.
  • 如果用户不提供拷贝构造, 编译器会自动提供一个默认的拷贝构造(完成赋值动作—浅拷贝).

拷贝构造和无参构造 有参构造的关系
如果用户定义了拷贝构造或者有参构造 都会屏蔽无参构造.
如果用户定义了无参构造或者有参构造,不会屏蔽拷贝构造

  • 拷贝构造几种调用形式

1.旧对象给新对象初始化 调用拷贝构造.
2.给对象取别名 不会调用拷贝构造.
3.普通对象作为函数参数,调用函数时会发生拷贝构造.
4函数返回值普通对象(Visual Studio会发生拷贝构造)(Qtcreater,linux不会发生).

  • 拷贝构造的深拷贝和浅拷贝

默认的拷贝构造 都是浅拷贝
如果类中没有指针成员,不用实现拷贝构造和析构函数
如果类中有指针成员,必须实现析构函数释放指针成员指向的堆区空间,必须实现拷贝构造完成深拷贝动作.

对象数组

对象数组:本质是数组,数组的每个元素是对象.

explicit关键字

  • explicit防止构造函数隐式转换

//构造函数隐式转换(类中只有一个数据成员)

new和delete堆区空间操作

1.new和delete操作基本类型的空间

  • new和malloc delete和free没有区别
  • 区别:new不用强制类型转换;new在申请空间的时候可以初始化空间内容.
    2.new和delete操作类空间
  • malloc不会调用构造函数 free不会调用析构函数
  • new 会调用构造函数 delete调用析构函数
    在这里插入图片描述
  • 基本类型的对象没有析构函数,因此回收基本类型的数组空间用delete和delete[]都可以,但为了规范,不建议用delete。

静态成员

定义:类的对象 拥有独立的普通成员数据
static修饰的成员叫静态成员.
static修饰的静态成员数据必须类中定义 类外初始化.
静态成员数据,可以通过类名称直接访问(属于类)

单例模式

  • 单例模式的类只能实例化一个对象.

this指针

  • 普通成员函数 默认有一个this指针 指向调用该成员函数的对象.
  • this完成链式操作.

友元

  • 类将数据和方法封装在一起 加以权限区分 用户只能通过公共方法操作私有数据(封装性)
  • 主要用于运算符重载.
  • 一个函数或者类 作为了另一个类的友元 那么这个函数或类就可以直接访问另一个类的私有数据.

运算符重载

  • 运算符重载是对已有的运算符指定新功能.不能创建新运算.
    运算符重载关键字operator
    思路:

1.弄懂运算符的运算对象的个数(个数决定了重载函数的参数个数)
2.识别运算符左边的运算对象是类的对象还是其他.
类的对象:全局函数实现(不推荐) 成员函数实现(推荐,少一个参数)
其他:只能是全局函数实现.
3.可以重载的运算符
在这里插入图片描述
重载++运算符
++a(前置++),它就调用operator(a).
a++(后置++),它就调用operator++(a,int).

函数模板

  • 将功能相同,类型不同的函数(类)的类型抽象成虚拟的类型.当调用函数(类实例化对象)的时候,编译器自动将虚拟的类型具体化.这个就是函数模板(类模板).
  • 关键字template;

函数模板会编译两次:
第一次:是对函数模板本身的编译
第二次:函数调用处将T的类型具体化
函数模板目标:模板为了实现泛型,可以减轻编程的工作量,增强函数的重用性.

  • 1.函数模板和普通函数都识别.(优先选择普通函数)
  • 2.如果想强制使用函数模板
  • e.g swapall<>(a,b);(加上<>)

  • 3.函数模板自动类型推导时,不能对函数的参数进行自动类型转换.
  • 4.如果函数模板显示指明T的具体类型,这时函数模板的参数可以自动类型转换.
    5.模板的局限性
  • 当函数模板推导出T为数组或者其他自定义类型数据,可能导致运算符不识别.

解决方法一:运算符重载
方法二:将函数模板具体化.

纯虚函数

  • 只要有一个纯虚函数,这个类称为抽象类.
  • 抽象类特点:
  • 1.无法实例化对象

  • 2.抽象类的子类,必须要重写父类中的纯虚函数,否则也属于抽象类.

虚析构与纯虚析构

多态使用时,如果子类中有属性开辟到堆区,父类指针在析构时候,不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄漏.

  • 虚析构和纯虚析构共性:
    可以解决父类指针释放子类对象时不干净的问题.
    都需要具体的函数实现.
  • 区别:
  • 如果是纯虚析构,该类属于抽象类,无法实例化对象

虚析构语法: virtual ~类名(){ }
纯虚析构语法: virtual ~类名()=0; 类名::~类名(){};

  • 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构.

类模板

  • 类模板将类中类型抽象成虚拟类型.
  • 1.类模板 实例化对象不能自动类型推导
  • 2.类模板 实例化对象必须指明T的类型.

STL的概述

STl的六大组件:容器,算法,迭代器,适配器,仿函数,空间配置

  • 容器:存放数据
  • 算法:操作数据
  • 迭代器:算法通过迭代器操作容器
  • 适配器:为算法提供更多的接口.
  • 仿函数:为算法提供策略
  • 空间配置:为算法,容器提供动态空间.

Vector容器

  • vector容器:单端动态数组容器.

push_back尾部插入元素,pop_back尾部删除元素
front()头元素,back()尾元素
begin()得到的是容器的起始迭代器(首元素的位置)
end()得到的是结束迭代器(尾元素的下一个元素位置)
必须包含头文件:#include
在这里插入图片描述

deque容器

  • 双端动态数组
    在这里插入图片描述
  • Deque容器和vector容器最大差异

1.deque允许使用常数项时间对头端进行元素的插入和删除操作
2.deque没有容量的概念.

stack栈容器

  • stack是一种先进后出的数据结构
  • 操作数据的一端叫栈顶.
  • top永远指向栈顶元素.
  • 栈容器没有迭代器.不支持遍历行为.

queue队列容器

  • queue是一种先进先出的数据结构.
  • 出数据的一端叫队头,入数据的一端叫队尾.
  • queue容器没有迭代器,不支持遍历行为.

list容器

  • 双向循环链表
  • list的迭代器是双向迭代器.

set容器

  • set容器只有键值,在插入数据的时候自动根据键值排序.不允许有相同的键值.不能修改set容器的元素值,会破坏set的数据结构.set容器的迭代器是只读迭代器(const_iterator).
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南方的守候

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值