C++学习笔记 - 类
1. 常成员函数的const必须出现在声明和定义中。
2. 类的成员函数只能重载本类的其它成员函数,成员函数与类外的非成员函数、其它类的成员函数无关。
3. 类内部定义的成员函数,自动作为inline处理。
4. 在成员函数的声明和定义处指定inline都是合法的,任选一个位置都行。但是由于inline函数必须在调用它的每个源文件中可见,所以不在类定义中定义的inline函数,其定义通常应放在类定义的同一头文件中。
5. 类的声明是一个不完全类型,不知道类的具体细节,所以不能定义该类的对象,只能定义指针、引用,用于声明形参、返回类型。所以类中不能定义该类的对象作为数据成员,只能是指针或引用。
6. 在成员函数内部显式引用this通常是不必要的,但有一种情况下必须这样做:当我们需要将一个对象作为整体引用而不是引用对象的一个成员时。最常见的情况是该函数返回对调用该函数的对象的引用。( ClassA & ClassA::doit() { return *this; } )
7. 非常成员函数中this是指向类类型的const指针,可以改变this指向的值,不可改变this保存的地址。在常成员函数中this是指向const类类型对象的const指针,既不能改变this指向的对象,也不可改变this保存的地址。不能从常成员函数返回指向类对象的普通引用,声明函数的时候必须是const的引用。返回引用的好处是可以将一系列操作串起来( a.b().c().d(); )。但b有可能是常成员函数,而c不是。则在const对象上调用非常成员函数是行不通的。解决办法是重载b,一个是const的,一个不是const的。
8. 有时希望类的数据成员在常成员函数中也可以被修改,可以把这个数据成员声明为可变数据成员,只需要将mutable放到声明前面。
9. 构造函数不能是const的。构造函数的工作是初始化对象,不管对象是否为const。
10. 必须在初始化列表中进行初始化的成员:a)没有默认构造函数的类类型成员,b)const成员,c)引用类型成员。
11. 初始化列表的顺序并不是成员被初始化的顺序,而是定义成员的顺序。
12. 可以传形参的表达式给初始化列表中的初始化式( X(int v) : i(v), j(v*v) {} )。
13. 类通常应该定义一个默认构造函数,在默认构造函数中给成员提供的初始值应该指出该对象是空的。
14. 静态数据成员可以声明为任何类型,常量、引用、数组、类类型等。必须在类定义体的外部定义,静态成员不是普通成员,不能在构造函数中初始化,而是在定义时初始化。但当是static const int时,可以在类定义体中进行初始化,不过仍必须在类的定义休之外进行定义。
15. 静态成员函数不是任何对象的组成部分,所以不能被声明为const。静态成员函数也不能声明为虚函数。
16. 在类外部定义静态数据成员、静态成员函数时,无须重复指定static保留字。
17. 如果类定义中有自定义的构造函数,则编译器不会提供默认构造函数。但是就算有自定义的构造函数,编译器也会提供复制构造函数。
18. 为了禁止复制,必须显式声明复制构造函数为private。因为如果不写编译器会合成一个默认的。
19. 如果类没有定义自己的赋值操作符,编译器会生成一个。可以使用合成复制构造函数的类通常也可以使用合成赋值操作符,如果类需要定义复制构造函数,那么它也需要定义赋值操作符,要将这两个操作看成一个单元,如果需要其中一个,肯定也需要另外一个。
20. 许多类并不需要显式析构函数,析构函数通常用于释放在构造函数或对象生命期获取的资源。
21. 如果类需要析构函数,则它也需要赋值操作符和复制构造函数。
22. 与复制构造函数或赋值操作符不同,编译总是会为我们合成一个析构函数,即使我们自己已经写了一个,合成析构函数仍然运行。合成析构函数按成员在类中声明次序的逆序销毁每个非静态成员。