跳转至

Week3 Class

::resolver(解析器)

  • <Class Name>::<function name>

  • ::<function name>(代表是全局的)

this指针

this指针是所有成员函数的一个隐藏参数,类型就是结构的类型,也就是说

void Point::move(int dx,int dy);  // can be recognized as 
void Point::move(Point *this, int dx, int dy);

Class

  • In C++,separated .h and .cpp file are used to define one class
  • Class declaration and prototypes in that calss are in the header file(.h)(类的声明和该类中的函数原型应当放在头文件中)
  • All the bodies of these functions are in the source file(.cpp)(所有这些函数的实现都放在源文件中)

Tip

我们需要区分一下Declarations和Definitions,Declarations意指声明,声明向编译器介绍一个标识符的名称和类型,但不分配存储空间或提供实现细节;Definitions意指定义,其不仅包含声明中的所有信息,还分配存储空间或提供实现细节。

不能放在头文件中的内容:

  1. 全局变量的定义
  2. 函数的定义(非内联函数)

因为当一个头文件被多个源文件包含时,如果头文件中有定义,那么这些定义会在每个包含该头文件的源文件中出现,导致链接时出现多重定义错误

#include回顾:

#include指令的主要功能是将指定的文件内容插入到当前的C++源文件中#include语句所在的位置,在实际编译之前由预处理完成

  • #include "xx.h"会在当前源文件所在的目录中查找该头文件,如果没找到,再到编译器预定义的或命令行中指定的目录中查找,通常用于包含自己编写的头文件
  • #include<xx.h>会直接在预定义的系统目录中查找头文件,跳过当前目录的搜索,通常用于包含标准库或系统提供的头文件
  • #include<xx>#include<xx.h>功能相同

标准头文件结构

#ifndef HEADER_FLAG
#define HEADER_FLAG

#endif 

Initialization and Clean-Up

Constructor(构造函数)

构造函数的名字和类的名字是相同的

Initializer list

  • 成员变量可以在定义的时候被初始化,如
struct Point{
    int x = 0;
    int y = 0;
}
  • 或者也可以使用构造函数初始化列表来初始化类成员变量。初始化列表是放在冒号后面,函数体之前的部分,格式为成员变量(初始值),多个成员变量之间用逗号分隔,这种方式比在构造函数体内赋值更高效,特别是对于那些无法默认构造的成员变量来说是必需的。
struct Point{
    Point(xx,yy);
    int x;
    int y;
};
Point::Point(int xx, int yy):x(xx),y(yy){}

The default constructor(默认构造函数)

默认构造函数是指没有参数或者所有参数都有默认值的构造函数(严格定义“默认构造函数是指可以被无参数调用的构造函数”)

注意

如果我们定义了任何构造函数但是没有定义默认构造函数,那么需要默认构造的场景就会出错

"auto" default constructor(自动默认构造函数):如果你自己定义了任何构造函数,那么编译器会确保对象创建时总会调用这个构造函数,并且不会自动生成默认构造函数;只有当类完全没有定义任何构造函数时,编译器才会自动为你创建一个默认构造函数,这个自动生成的默认构造函数不带参数,也不执行任何初始化

The Destructor(析构函数)

析构函数的命名是~+类的名字,析构函数没有参数

析构函数调用的时间:

  • 析构函数会在对象超出作用域时被编译器自动调用,也就是说,当一个对象的生命周期结束时(比如局部变量所在的函数执行完毕,动态分配的对象被显式删除),析构函数就会自动触发
  • 我们通常不会看到析构函数的显式调用代码,它是由作用域结束时编译器隐式调用的。

Tip

析构的顺序和构造的顺序相反,先构造的后析构,后构造的先析构(因为可能存在构造的依赖关系)

储存分配和初始化的区别

  • 编译器会在作用域开始处就分配该作用域内的所有存储空间,这意味着编译器会在函数或代码块开始执行时就为其中所有的局部变量预留内存空间
  • 对象的构造函数调用并不是在分配存储空间的时候发生的,而是在程序执行到定义该对象的那一行代码才会调用,也就是说创造了一个“已分配但未初始化”的时间窗口。

Tip

变量的作用域和生存期

变量类型 作用域 生存期 特点
本地变量(局部变量) 仅限于声明它的代码块内部(如函数、循环或条件语句块内) 从声明点开始,到代码快执行结束时终止 其他函数或代码块无法访问,每次执行代码块时重新创建
全局变量 整个程序或模块 从程序开始到程序结束 任何函数或代码块都可以访问和修改
静态变量 与局部变量相同,仅限于声明它的代码块 从第一次执行声明到程序结束 保留值,在函数多次调用间保持状态

评论