C++_基础知识点_1

0 默认参

链接_视频

  • 函数允许提供默认参。
  • 默认参数可以写在声明或定义处,但只能出现在一个地方,一般写在声明处。
  • 当一个参数有默认参时,该参数右边必须都出现默认参。

1 const常量

链接_视频

  • const用于修饰变量,将变量变为常量,常量一旦定义,就不可以修改。
  • 编译器在程序的编译时期做的检查,即定义后是不可以通过赋值修改的,但在运行时期时可以修改的。

2 const指针

链接_视频

  • const T*表示不能修改指针指向的内容,指针本身的值可以修改。
  • T const*const T*,表示不能修改指针指向的内容,指针本身的值可以修改。
  • T* const表示该指针是一个常量,意味着指针本身的值不能被修改,但是指针指向的内容可以修改。
  • const T* const表示指针指向的内容和指针本身均不能被修改。
  • const_cast类型转换可以用于去除const修饰。

3 内联函数

链接_视频

  • inline函数能够节省进出函数的系统的耗时。
  • inline是对编译器的建议,编译器可以根据函数的大小自动选择是否内联。
  • debug版本没有inline,为了方便调试。
  • 内联函数必须写在头文件中。

4 引用

链接_视频_1
链接_视频_2
链接_视频_3

  • 引用&是变量的别名。
  • 引用在定义时必须初始化,且不能使用常量为引用赋值。
  • 只有常量引用可以使用常量来初始化。const int& crefN = 12;
  • 引用的关系一旦建立则无法修改。
  • 不存在二级引用,可以使用指针的引用来替代二级指针。

5 作用域与数据隐藏

链接_视频

  • 作用域包括全局作用域,名字空间域,局部作用域,块作用域和类作用域。
  • 在不同的作用域可以定义多个相同名字的变量。
  • 内部的变量会隐藏外部的变量(从内->外查找)。

6 名字空间

链接_视频_1
链接_视频_2

  • 关键字namespace
  • 一种作用域的划分,通常用于区分项目中模块或组件。
  • 名字空间可以分开使用。(在多个地方使用同一个名字空间
  • 名字空间可以嵌套。
  • 名字空间可以取别名。namespace t = test
  • 单独使用::表示使用全局作用域。
  • 名字空间的使用方法:
    1 直接使用。名字空间::内容 (推荐
    2 声明名字空间。using namespace 名字空间
    3 声明只使用名字空间的部分变量或函数。using 名字空间::内容

7 函数重载

链接_视频_1
链接_视频_2

  • 函数重载指C++中相同名字的函数。(C中是不支持重载的
  • 函数重载的条件: (函数要素:函数名,函数参数,函数返回值,函数的调用约定
    1 函数名必须相同。
    2 函数参数个数不同,类型不同,顺序不同。
    3 函数返回值,调用约定不做考虑。
    4 作用域相同。

8 面向对象及类

链接_视频_1
链接_视频_2
链接_视频_3
链接_视频_4

  • 对象 = 数据(数据类型) + 行为(函数)
  • 面向对象特点:
    1 封装。(数据成员+成员函数
    2 继承。
    3 多态。
  • C++structclass的唯一区别就是成员的默认访问权限。(结构体默认是公有public权限,类默认是private权限

9 this指针

链接_视频 (18

  • 同一个类的对象,其成员函数地址是一样的,表示同一个类的对象的成员函数共用的。(数据是独立的,成员函数是共用的
  • 成员函数调用时会偷偷的传递this指针,通过寄存器ecx传递,这种传递方式称为thiscall

10 构造函数

链接_视频_1
链接_视频_2

  • 用于初始化对象的成员。
  • 由编译器在合适的时机调用。
  • 不允许有返回值。
  • 可以有参数,支持默认参。
    1 仅有一个参数时,该函数即表示构造函数,又表示一种隐式转换,从而支持CTest obj = 1,可以使用关键字explict表示支持显示调用构造函数,不允许隐式转换。
    2 支持函数重载。
    3 如果不重载构造函数,编译器会提供一个无参的默认构造函数。
    1
    2
    CTest() = default;  // 表示使用默认的构造函数
    CTest() = delete; // 表示禁止使用某函数(删除
  • 构造函数可以使用初始化列表来初始化成员。
  • 构造函数通常不要手动调用。

11 析构函数

链接_视频

  • 完成资源的反初始化。(释放资源
  • 在类名前加~
  • 由编译器决定调用时机,不需要手动调用。
  • 不能有参数和返回值。
  • 不能重载。

12 构造函数与析构函数的调用时机

链接_视频

  • 构造函数和析构函数需要时公有的。
  • 栈上的局部对象的调用时机:
    1 构造: 声明该对象时构造。
    2 析构: 对象出作用域时调用析构。
  • 全局对象(堆? no)的调用时机:
    1 构造: 进入到main函数之前。
    2 析构: 出main函数之后。

13 拷贝构造函数

链接_视频

  • 作用: 本质上也是一种构造函数。
  • 调用时机: 当用一个对象创建另外一个对象时调用。CTest t2 = t1;
  • 缺省的拷贝构造函数的作用: 完全的把对象1拷贝给对象2。(memcpy

14 浅拷贝与深拷贝

链接_视频

  • 缺省的拷贝构造函数中是浅拷贝。(类似两个指针指向同一个堆空间
  • 当对象中的成员函数存在一种需要分配的资源时(malloc),为了避免在析构时重复释放,需要重写(深)拷贝构造函数或禁用拷贝构造函数。

15 newdelete运算符

链接_视频_1
链接_视频_2

  • new分配空间,调用构造函数。
  • delete调用析构函数,释放空间。
  • newdelete都是在堆上分配和释放空间。
  • 相比于Cmallocfreenewdelete能够调用类的构造和析构函数。
  • 对于基本数据类型(相对于自定义的类对象)而言,newdelete仅仅分配或释放内存空间。(intfloat,…
  • 当申请一个堆上的对象时,使用newdelete,不能使用mallocfree替换。
  • new []分配数组,delete []释放数组空间。
    1
    2
    CTest* pt = new CTest[10];
    delete [] pt;
  • new []delete []要配套使用,特别是申请对象数组时。
  • vs编译器会在new []申请对象数组时,在堆开始的前4个字节写入当前数组的长度,用于记录delete []释放时,析构调用的次数。

16 类的派生与继承

链接_视频_1
链接_视频_2
链接_视频_3

  • 子类(派生类),父类(基类)。
  • 保护成员(protected)除了自身或派生类以外,不能在其他类外使用。
  • 继承的可见性
    父类 继承方式 子类
    公有继承(public)
    公有成员(public) 公有成员(public)
    保护成员(protected) 保护成员(protected)
    私有成员(private) 不可见
    保护继承(protected)
    公有成员(public) 保护成员(protected)
    保护成员(protected) 保护成员(protected)
    私有成员(private) 不可见
    私有继承(private)
    公有成员(public) 私有成员(private)
    保护成员(protected) 私有成员(private)
    私有成员(private) 不可见
  • 继承的可见性是由编译器在编译时刻做的限制。
  • 子类指针转换为父类指针是安全的,父类指针转换为子类指针是不安全的。(数据成员个数问题,指针越界

17 派生类中构造与析构顺序

链接_视频

  • 派生类的构造顺序,先父类后子类。
  • 派生类的析构顺序,先子类后父类。
  • 成员类的构造顺序,先成员类后自己。
  • 成员类的析构顺序,先自己后成员类。

18 初始化列表

链接_视频

  • 初始化列表作用:
    1 调用父类的有参构造。
    2 对于自身成员的初始化。
    3 对于常量成员的初始化。

19 函数隐藏

链接_视频

  • 函数隐藏的条件:
    1 作用域不同。(父类与子类
    2 函数名相同。
    3 参数列表,调用约定和返回值不考虑。

20 多态与虚函数

链接_视频_1
链接_视频_2
链接_视频_3

  • 父类中使用virtual关键字将成员函数变为虚函数。
  • 虚函数的调用原理:
    1 虚函数的调用方法是间接调用,先查虚表地址,再查虚表中的虚函数指针。
    2 增加了虚函数virtual关键字的对象的头部4个字节是虚表地址。(单继承的情况下

21 函数覆盖 (虚函数

链接_视频_1
链接_视频_2

  • 函数覆盖的条件:
    1 作用域不同。(父子类之间继承关系
    2 函数名,参数列表(参数的个数,顺序,类型),返回值,调用约定(__thiscall)必须相同。
    3 有virtual关键字。
  • 虚表大小的确定:
    1 由编译器在编译时期确定的。
    2 在运行时的内存中并没有个数的表示。
  • 虚表中虚函数的顺序:
    1 子类继承父类的所有的虚函数。(公有
    2 父类的虚函数顺序决定了子类虚函数的顺序。
    3 子类重写了父类的某虚函数,则会在子类自己的虚表中覆盖对应位置的函数。
    4 子类未重写某虚函数,则直接继承父类的该虚函数。
    5 子类自己的虚函会出现在自己虚表中父类所定义的虚函数后面。

22 虚函数的调用方式

链接_视频

  • 直接调用指根据函数名称,直接调用该函数。(编译器在编译时就确定了
    1 普通函数的调用。
    2 对象的普通成员函数(相对与虚函数而言)的调用。
    3 对象的虚函数的调用。
  • 间接调用(虚调用,即通过查虚表来调用)指通过查找对象的虚表下表来调用函数的方法。(在运行时期确定调用谁
    1 通过对象的指针调用虚函数。
    2 通过对象的引用调用虚函数。

23 函数覆盖重载隐藏的调用秘笈

链接_视频_1
链接_视频_2

  • 讲的太TM细了,高手 !!!
  • 调用者的类型决定查找的起点:
    • 1 在调用者的类中,查找同名函数:
      1.1 如果没有,则往上一层查找,如果均找不到,则报错。(未定义
      1.2 如果有,则不会往上面查找,可见的域就是当前找到的同名函数所在的域。(函数隐藏
    • 2 在当前可见的域中,找到最佳函数。(函数重载规则
      2.1 如果唯一的最佳函数不是虚函数,则该调用是直接调用。
      2.2 如果唯一的最佳函数虚函数,判断调用者是否是指针或引用:
      2.2.1 调用者是指针或引用,则是间接调用。(函数覆盖规则  
      2.2.2 调用者不是指针或引用,则是直接调用。  
  • 直接调用: 谁的类型调谁。
  • 间接调用: 谁的虚表调谁。
  • 版权声明: 本博客所有文章均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2020-2021 Hang Liu
  • Powered by Hexo Theme Ayer
  • PV: UV: