C++归纳整理

本文详细介绍了C++的关键特性,包括内联函数、函数重载、extern "C"的使用、函数模板和类模板、构造函数与析构函数、静态成员与静态成员函数、继承与多态、STL和设计模式等,旨在帮助读者深入理解C++的核心概念。
摘要由CSDN通过智能技术生成
  1. 内联函数

    • 关键字inline
    • 功能简单、规模较小且使用频繁的函数
    • 在编译的时候将函数嵌入在调用它的地方,可以减少参数传递和控制转移等的开销
    • 定义位于类声明中的函数会自动被认为内联函数
  2. 函数重载(多态)

    • 在同一个作用域中,两个及以上函数的函数名相同,但是参数类型或者参数数量不同,编译器将根据参数类型和参数个数自动匹配并调用,这就是函数重载。
    • 注意:编译器将类型引用和类型本身视为相同的参数。
    • 类的成员函数可以重载,不同类的同名函数不是重载
  3. extern “C”

    • 实现C++调用C语言的代码,提示编译器这部分代码按照C语言进行编译。
    • 编译不同之处:C++支持函数重载,函数编译过程中会将函数名以及参数类型加入到编译后的代码中,C语言不支持函数重载,因此编译过程中只将参数名加入到编译后的代码中。
  4. 函数模板和类模板

    • C++多态性的体现,实现高效的代码重用
    • 关键字template
    • 函数模板
      • 函数模板可以重载
      • 遇上同名普通函数时,编译器会优先选择普通函数,除非函数模板能产生更好的参数类型匹配,可以通过空模板实参列表的语法限定编译器只能通过模板匹配
    • 类模板
      • 子类从模板类继承时,需要制定基类的参数类型,如class B: public A
  5. 类的成员函数

    • 可以重载
    • 可以使用默认参数
    • 一般在头文件中声明,在源文件中定义
  6. 封装

    • 类的定义过程,将抽象得到的数据成员和函数成员形成一个统一的整体
  7. 类的访问修饰符

    • public:类本身、子类、对象
    • protect:类本身、子类
    • private:类本身
  8. 构造函数

    • 完成对象的初始化工作
    • 如果定义了一个带参数的构造函数且不是所有的参数都有默认值,那么必须定义一个不带参数的构造函数,否则调用不带参数的构造函数时会报错
    • 子类中构造函数的调用顺序:基类构造函数(按继承顺序)、派生类对象成员的构造函数(按声明顺序)、派生类构造函数
  9. 复制构造函数

    • 什么时候调用

      • 用已经定义的对象去初始化其它对象的时候
      • 函数的形参是对象类型,完成形参和实参结合的时候
      • 函数返回值是对象,函数执行完返回结果的时候
    • 什么时候需要自定义复制构造函数(完成深复制)

      • 类数据成员有指针的时候
      • 类数据成员管理资源的时候,如打开文件
      • 需要析构函数释放资源的时候
    • 禁止调用复制构造函数

      class Uncopyable {
      private:
      	Uncopyable(const Uncopyable &);	//阻止拷贝构造
      	Uncopyable &operator=(const Uncopyable &);	//阻止赋值运算符
      };
      
  10. 析构函数

    • 完成对象删除前的清理工作,对象删除前系统自动调用
    • 不可以重载
    • 可能会被继承的类的虚函数应该声明为虚函数,这样可以使用基类的指针释放子类的空间,否则会发生内存泄漏
    • 析构函数调用顺序与构造函数相反:派生类析构函数体、派生类成员对象析构函数、基类析构函数
  11. static数据成员

    • 实现同类不同对象之间的数据共享

    • 访问 类名::静态对象名

    • 需要在类外初始化,初始化时不加static

      int Martain::martain_count = 2;
      
    • 存储在静态存储区,对象的成员变量在堆或栈中生成

    • 优点:避免二义性,节省存储空间

  12. static函数成员

    • 主要用于访问静态数据成员,需要通过对象名才能访问非静态数据成员,维护不同对象之间共享的数据
    • 可以通过类名和对象名调用,但是其意义都是相同的
    • 没有this指针
  13. 动态内存分配与释放

    • new/delete:C++提供的关键字
    • malloc/free:C提供的函数,需要指定申请空间的大小
  14. 深复制和浅复制

    • 默认复制构造函数都是浅复制
    • 浅复制在遇到含有指针的对象类型的时候容易出现问题,复制后的对象和原来的对象指向同一块内存空间
      • 一个对象对内存存储数据的修改会影响到另一个对象
      • 可能会重复释放同一块内存,造成运行错误
  15. const关键字

    • 数据保护机制
    • 常数据成员只能使用初始化列表初始化
    • 常函数成员可以使用类中所有的数据成员,但是不可以修改它们,在声明和定义的时候都需要在结尾加上const关键字
    • 指向常量的指针(指针本身可变,*与变量名被分隔开),常指针(指针不能再指向其它的值了,*与变量名在一起)
    • 常对象,只能访问类的const成员
  16. 运算符重载

    • operator op(参数列表)
    • 可以重载为成员函数或者非成员函数,重载为成员函数参数个数是实际参数个数-1(对象本身就是一个参数),非成员函数(要声明为类的友元函数)是实际参数个数
    • 只能重载为成员函数的:=/[]/()/->
    • 不能重载的:类型转换操作符(const_cast synamic_cast reinterpret_cast static_cast)/typeid/类限定符/./.*/?:/sizeof
    • 重载后的参数至少有一个是用户自定义的类型,不能创建新的运算符、不能修改原有运算符的规则
  17. 继承

    • 公有继承、私有继承、保护继承
    • 公有继承:继承之后,父类成员访问属性在子类中不变,子类成员及子类对象可以访问父类的公有成员和保护成员,但是无法访问父类的私有成员
    • 私有继承:继承之后,父类的所有成员都变为子类的私有成员,子类成员可以访问父类的公有成员和保护成员,不可以访问父类的私有成员
      • 子类对象不可以访问父类的任何成员,子类再派生新的子类的时候,父类成员无法再被继承(已经全部变为子类的私有成员了),相当于阻断了父类的继承机制
    • 保护继承:继承之后,父类成员访问属性在子类中不变,子类成员可以访问父类的公有成员和保护成员,但是无法访问父类的私有成员,子类对象无法访问父类的成员,但是子类可以继续派生新的子类
    • 赋值兼容原则:派生类对象可以隐含转换为基类对象、派生类的对象可以初始化基类的引用、派生类指针可以隐含转换为基类指针
  18. 多态

    • 特殊多态:重载多态、强制多态;一般多态:包含多态、参数多态
    • 虚函数:基类中用virtual关键字声明的函数,可以用基类的指针调用派生类的函数,动态绑定的基础,基于虚函数表和虚表指针实现
    • 抽象类:有虚函数的类
    • 纯虚函数:只有函数声明,没有函数定义,格式是虚函数声明之后加上 =0,有纯虚函数的类是接口类,更高层次的抽象,无法实例化,必须定义析构函数
    • 多态基类必须定义虚析构函数,否则会内存泄漏
  19. STL

    • 由一些集合类及在这些类上操作的算法构成,包括容器、算法、迭代器、函数对象
    • 容器
      • 顺序容器:向量vector、双端队列dqueue、列表list
        • vector:动态数组,自动分配内存
        • list:双向链表
      • 关联容器:集合set、多重集合multiset、映射map、多重映射multimap
    • 迭代器iterator:面向对象版本的指针,遍历容器
    • map:内部实现一般为平衡二叉树
  20. 设计模式

    • 面向对象设计原则1:针对接口编程,而非针对实现编程
    • 面向对象设计原则2:优先使用对象组合,而不是类继承
    • 观察者模式:定义对象间的一对多依赖关系,当一方的对象改变状态时,所有依赖者都会被通知更新,也叫发布-订阅模式,被依赖的一方叫目标或主题(Subject),依赖方叫观察者(Observers)
  21. 异常捕获

    • 只用来处理确实可能不正常的情况
    • 构造器和析构器不应该使用异常
    • 如果try语句块无法找到与之匹配的catch语句块,则它抛出的异常将中止程序的执行
    • 使用对象作为异常,用值传递的方式抛出对象,引用传递的方式捕获对象
    • 函数的异常声明列表void func() throw (int, double, A, B, C){…}
      • 交代可能抛出的异常类型
      • 可以在声明时写,也可以在定义时写,若都写要保持一致
      • void func() throw ()表示不抛出任何类型的异常
      • 若不交代能抛出什么类型的异常,那么可以抛出任何类型的异常
      • 若抛出没有交待的异常,编译时不会出错,但在运行时, Dev C++ 编译出来的程序会出错;用 Visual Studio 2010 编译出来的程序则不会出错,异常声明列表不起实际作用
    • 标准异常类,从exception派生而来
  22. 其它

    • 系统不会初始化局部变量
    • 一个函数体中可以存在同名变量,前提是作用域不同
    • 存储在静态存储区的变量会在程序刚开始运行时会被初始化,这是唯一一次被初始化
    • 存储在静态存储区的变量:全局变量、静态变量
    • 全局变量和局部变量同名时,通过域名在函数中引用全局变量,否则引用的全是局部变量
  23. 变量在内存中的位置(自上而下)

    • 代码区:存放程序的执行代码,通常只读,程序运行前大小就已经确定了,const修饰的全局变量存储在这里
    • 静态存储区:生命周期是整个程序的运行周期
      • 初始化数据区:已被初始化的全局变量或者静态变量
      • 未初始化数据区:未被初始化的全局变量或静态变量
    • 栈区:存储临时创建的局部变量、局部变量、函数参数、函数返回值等,编译器自动分配释放,向下有限扩展,const修饰的局部变量
    • 堆区:存放动态分配的内存,大小不固定,动态申请后向上添加到栈区,释放后从堆中删除,程序员负责分配释放,如果不释放,程序结束后OS释放
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值