1.类
- 带指针的类
- 不带指针的类:大多数不需要析构函数
2.定义头文件
- 防御式代码,避免多次include时重复导入
1 | #ifndef _COMPLEX_ |
- 头文件布局:
- 前置声明
- 类声明
- class head
class Complex - class body : 定义数据和函数
- class head
- 类定义
1 | Class A |
3.函数
构造函数
- 默认参数
- initialization list,只有构造函数有
- 用法:
1 | A(int arg1, int arg2) |
- 如果构造函数的参数是类型本身,那么叫拷贝构造。
- 只要类带指针必须有拷贝构造函数。PS: 同时要有拷贝赋值函数。 编译器会默认生成,但是需要根据情况自己写。
inline函数:
- 当一个函数在class body内定义并且实现了功能,则会自动成为inline函数。
- 在外部实现并且加上inline关键字的函数,只是作为inline函数的一个候选人,是否成为一个inline函数完全看编译器会不会这样来编译它。
函数重载
- CPP中重载函数在代码中同名,但是在编译后不同名。
- 如果出现一个函数
foo()和foo(int i = 0)这样的情况,实际上是不行的,因为编译器认为在调用的无参版本时两个函数都可以,这样就出现了错误。
const member functions (常量成员函数)
- 以下面的函数为例,参数括号后加上const修饰符,则说明这个函数是不改变对象中数据的值。
1 | double real () const { return re; } |
- 在函数的使用上可能与如下的方式,说明我生成的对象c1中的数据是不希望修改的,那么如果real函数中没有const的话编译时会报错。因为如果没有const,说明real函数可能会修改对象中的数据的值,但是我们定义的c1又是一个不会被修改的,那么就有矛盾了。
1 | const complex c1() |
pass(return) by value vs pass(return) by reference (to const)
&这个符号在c中是取地址的操作,在C++中也有这个用发,但是多了一个用法。比如如下的代码中:
1 | complex& operator += (const complex&); |
- 参数类型后面加
&说明这个参数是按引用传递,本质就是指针。如果不加const修饰,则函数中可以修改参数的值,如果加了则说明这个参数就是按指针传递给函数使用,但是不能修改其值。 - 通常来说尽可能用按引用传递,因为毕竟指针只有4个byte,对于多数情况来说是比较快速和省资源的(栈上的数据少)。但是如果遇到传递的值是char的,也可以安值传递。
- 传递者无需知道接受者是以reference的形式接收。传递者把对象传递个函数,但是函数是使用值形式的参数还是引用形式的参数完全看函数的定义,但是调用者无需关心。
何时使用value来传递呢?
- 如果函数的返回值是函数内部的一个local object就需要安值传递。因为在函数结束后对象就从栈中销毁了,此时用引用的话在获取值的时候,对象已经没了。
- ++所以是返回引用还是值,根本上要看这个返回值内存是在函数内还是函数外。++
友元函数
- 加
friend修饰符,只是告诉类某个函数是友元的,可以直接访问private的变量。 - ++相同class的各个对象互为friend(友元)++
1 | int foo(const complex& param) |
静态函数
- 与C#不同的是CPP中静态函数可以通过对象来调用,同时当有也可以用类+函数名的方式调用。即
1 | Class::StaticFuntion(); |
总结
- 数据一定放在private里面
- 参数和返回值尽可能用reference来传递,加不加const根据实际情况
- class body中函数如果没有修改数据则加const
- 构造函数尽量用初始列表