The header file🦒

Distinguish between definition and declaration

Definition of a class

  • In C++ ,separated .h and .cpp files are used to define one class.
  • Class declaration and prototypes(原型) in that class are in the header file(.h).
  • All the bodies of these functions are in the source file(.cpp).

The header files

  • If a function is declared in a header file,you must include the header file everywhere the function is used and where the function is defined.
  • If a class is declared in a header file,you must include the header file everywhere the class is used and where class member functions are define.

Header = interface

  • The header is a contract(合同) between you and the user of your code.
  • The compile enforces(强制执行) the contract by requiring you to declare all structures and functions before they are used.

image-20211206210305703

Declarations vs. Definitions 😎

  • A .cpp file is a compile unit
  • Only declarations are allowed to be in .h
    • extern variables
    • function prototypes
    • class/struct declaration

在头文件中只声明不定义是为了防止链接时重复定义导致错误

示例:新建如下文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//a.h
int golbal;
void f();

//a.cpp
#include"a.h"
int main(){
return 0;
}

//b.cpp
#include"a.h"
void f(){

}

Use the following command to compile.

1
g++ a.cpp b.cpp --save-temps -Wall

The purpose of the “–save-temps” option is to be able to save intermediate files during compilation.(保存中间文件), “-Wall” 输出所有警告。

结果如下:

image-20211206214215813

观察报错信息,发现是链接时发生错误,global重复定义导致出错。上面说过在预处理过程中,预处理器会把头文件中的东西一股脑的复制到.cpp中,所以当多个.cpp文件引用同一个头文件时,如果是分开编译不会报错,但是一旦进行链接,则在链接文件中就会同时存在来自不同.cpp文件的相同变量定义,导致链接错误。

a.cpp —(code pre-processing)—>a.ii—(Generating assembly code)—>a.s—(creating aim code)—>a.o+b.o—(ld)—>.out(编译过程)

#include

  • #include is to insert the included file into the .cpp file at where the #include statement is.
    • #include “xx.h” :first search in the current directory, then the directories declared somewhere.
    • #include<xx.h>: search in the specified dircetories.
    • #inlcude :same as #inlcude<xx.h>

Standard header file structure

1
2
3
4
5
6
7
#ifndef HEADER_FLAG

#define HEADER_FLAG

// Type declaration here...

#endif

采用标准头文件书写方式同样是为防止重复声明类,示例如下

假设我们有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//a.h
extern int global;
class A{

}

//b.h
#include"a.h"
extern A a;

//a.cpp
#include"a.h"
#include"b.h"
int main(){
return 0;
}

执行如下命令

1
g++ a.cpp --save-temps

结果如下:

image-20211206223433099

从错误信息可以看出错误是由calss A 重复声明引起的。导致这种情况发生的原因是头文件b.h include了 a.h,然后a.pp同时include 了a.h和b.h,这样就会导致头文件a.h中的内容在预处理阶段完成后会被复制到a.cpp中两次。我们可以查看一下a.ii

image-20211207114830532

为了避免这种情况发生,就需要采用标准头文件书写方式。

1
2
3
4
5
6
7
8
// a.h 标准书写方式
#ifndef _A_H_
#define _A_H_
extern int global;
class A{

}
#endif

修改完成之后再次进行编译

image-20211207115351829

程序成功编译。

Fields(成员变量), parameters(参数), local variables

  • All three kinds of variable are able to store a value that is appropriate to their defined type.
  • Fields are defined outside constructors(构造函数) and methods.
  • Fields are used to store data that persists throughout the life of an object. As such , they maintain the current state of an object. They have a lifetime that lasts as long as their object lasts.
  • Fields have class scope: their accessibility extends throughout the whole class, and so they can be used within any of the constructors or methods of the class in which they are defined.

constructor and destructor

  • The constructor is called automatically by the compiler when the object goes in the scope.
  • The constructor is called automatically by the compiler when the object goes out of scope.
  • The only evindence for a destructor call is the closing brace of the scope that surrounds the object.

Storage allocation(存储分配) 🐳

  • The compiler allocates all the storage for a scope at the opening brace of that scope.
  • The constructor call doesn’t happen until the sequence point where the object is defined.

Tip for new and delete

  • don’t use delete to free memory that new did’t allocate.
  • don’t use delete to free the same block of memory twice in succession.
  • use delete[] if you use new[]to allocate an array.
  • use delete (no brackes)if you used new to allocate a single entity.
  • it’s safe to apply delete to the null pointer (nothing happens)

access control – private

  • The private keyword means that no one can access that member expect inside function members of that type.(对内部成员函数可见)
  • private的这种限制仅仅在编译时刻。
  • Tip: 一个对象的成员函数可以访问相同类的另一个对象的私有成员。

Friends

  • to explicitly(明确) grant(权限)access to a function that isn’t a member of the structure.
  • The class itself controls which code has access to its member.
  • Can declare a global function as a friend, as well as a menber function of another class, or even an entire class as a friend.

image-20211207173030541

  • friend 是在编译过程进行检查的

class vs. struct

  • C++ 中class和struct是等价的,但有细微区别
  • class defaults to private
  • struct defaults to public

Initialization(初始化) vs. assignment(赋值)

image-20211207183636795

Public vs. Private

  • 通常将成员对象作为私有
    • 他们是底层实现的一部分
    • 新的class只拥有成员对象的部分公共接口
  • 如果你希望拥有成员对象的全部公共接口可以使成员对象为public

image-20211207190334782

继承和组合

  • 都是重用(reuse)的一种方式
  • 组合是拿已有的对象拼装出新的对象
  • 拿已有的类,在类的基础上进行一些改造扩充

image-20211207190935767

image-20211207191511599

  • Tips:如果父类当中有重载函数,子类当中有与父类重载函数其中一个相同的函数,那么子类中将仅有这一个函数,没有其它从父类中继承的重载函数。

Rules of references

image-20211208154943001

Pointers vs. References

image-20211208155933134

image-20211208171151881

image-20211208171216992