主要是自己看这本书的时候一些容易忘记的细节,可能你会说太细节了,但是每次回顾这些的时候,自己总能够同时想起其他的一些知识点。
本人是个新手,希望能够得到各路大神的指点!谢谢了!
本文是按章分的,以后在学习的时候还会不断更新!基本是书上的原话!
引用和拷贝构造函数
1、当按值传递对象的时候,编译器会调用拷贝构造函数,如果没有拷贝构造函数,那么编译器会创建默认的拷贝构造函数,而这个拷贝构造函数一般为 位拷贝。
2、拷贝构造函数的第一个参数貌似不能是类 而应该是引用。
常量
1、C中const的意思是“一个不能被改变的普通变量”,const常量总是占用存储而且它的名字是全局符。C编译器不能把const看成一个编译期间的常量。
2、通常C++编译器并不为const创建存储空间,相反的它把这个定义保存在它的符号表里。但是像 extern const int bufsize 中的extern强制进行了存储空间的分配(另外还有一些情况,如取一个const的地址,也要进行存储空间的分配),由于extern意味着使用外部链接,因此必须分配存储空间,这也就是说有几个不同的编译单元应当能够应用它,所以它必须有存储空间。
3、构造函数初始化列表 里的初始化发生在构造函数的任何代码执行之前。这是初始化所有const的地方。
4、要是类中有一个常量成员,在该类的所有对象中它都一样,则语法为:static const int A。在C++不支持该语法时,可用不带实列的无标记的enum实现:enum{ size = 100; }
5、const对象只能调用const成员函数。
6、关键字mutable指定一个特定的数据成员可以在一个const对象里改变。
7、const不能用于构造函数(一种解释为:构造函数本来就是为了初始化类中的数据成员,但是当你声明为const后就不能修改了,编译器就提示你这样做就没有必要了)
内联函数
1、宏定义:
#define BAND(x) (((x)>5&&(x)<10)?(x):0)
当 int i = 6; BAND(++i);后i的值为9 而不是7。
2、程序设计者出于效率考虑,不得不让一些数据成员成为public类型。
3、任何在类中定义的函数自动成为内联函数。
4、内联函数貌似可以重载。
5、预处理器不能检查类型和进行转换。
6、假如函数太复杂,编译器将不能执行内联。一般的,任何种类的循环都被认为太复杂而不扩展为内联函数。
7、假如要显式地或隐式地取函数地址,编译器也不能执行内联。因为这是编译器必须为函数代码分配内存从而产生一个函数的地址。但是当地址不需要时,编译器仍将可能内联代码。
8、只有在类声明结束后,其中的内联函数才会被计算。
名字控制
1、C/C++中static的两种基本含义(这两种基本含义经常是互相冲突的):
(1)在固定的地址上进行存储分配,也就是说对象是在一个特殊的静态数据区上创建的,而不是每次函数调用时在堆栈上产生的。
(2)对一个特定的编译单位来说是局部的。这样static控制名字的可见性,所以这个名字在这个单元或类之外是不可见的。这也描述了连接的概念,它决定连接器将看到哪些名字。
2、C和C++都允许在函数内部定义一个static对象,这个对象将存储在程序的静态数据区中,而不是在堆栈中。这个对象只在函数第一次调用时初始化一次,以后它将在两次函数调用之间保持它的值。
3、如果没有为一个内建类型的静态变量提供一个初始值的话,编译器也会确保在程序开始时它被初始化为零(转化为适当的类型)。注意零赋值只对内建类型有效,用户自定义类型+-
4、静态成员函数不能访问一般的数据成员,而只能访问静态的数据成员,也只能访问其他静态成员函数(当前对象的地址(this)是被隐式的传递到被调用的函数的。但一个静态成员函数没有this,所以它无法访问一般的成员。)
5、静态成员函数:它为全体对象服务而不是为一个类对象服务。当产生一个静态成员函数的时候,也就表达了与一个特定类的联系。 调用: X::f() 静态成员函数不能调用一般的数据成员,而只能访问静态数据成员,也只能调用其他的静态成员函数。
组合与继承
1、构造函数和析构函数不能被继承,必须为每一个特定的派生类分别创建。
2、Operator=不能被继承。
运算符重载
1、operator=只允许作为成员函数。
2、Explicit能够阻止构造函数的自动类型转换,如果仍然想利用该构造函数进行类型转换,必须显示的进行。( (B)A )
多态性和虚函数
1.纯虚函数能够通过生成一个编译错误来阻止对象切片。
2.对于在构造函数中调用一个虚函数的情况,被调用的只是这个函数的本地版本。也就是说,虚机制在构造函数中不工作。
3.构造函数是不能为虚函数的,但是析构函数能够且常常必须是虚函数。
4.不把析构函数设为虚函数是一个隐匿的错误,因为它常常不会对程序有直接的影响。但要注意它不知不觉的引入存储器泄露(关闭程序时内存未释放)。同样,这样的析构操作还有可能掩盖发生的问题。
5.必须为纯虚析构函数提供一个函数体。
6.纯虚函数不能是内联的。
7.必须为纯虚函数提供一个函数体。
8.如果不进行析构函数定义,编译器将会自动地为每个类生成一个析构函数定义,因此不会因为基类的析构函数为纯虚函数而是派生类为抽象类。
异常处理
1、c++中使用longjmp()的问题时它不能识别对象。特别是,当跳出某个作用域的时候,它不会调用对象的析构函数。而析构函数的调用在c++中使必需的操作,所以这种方法不能用于c++。(某些c++编译器包含了扩展的longkmp(),能够清除栈中的对象。但这种行为是不可移植的。)
2、一旦某个异常被抛出后,异常处理机制将会依次寻找参数类型与异常类型相匹配的异常处理器。找到第一个这样的异常处理器后,程序的执行流程进入这个catch子句,于是系统就可以认为该异常已经处理了。
3、当throw语句造成程序的执行过程从一个函数中返回时,这个函数中的对象的析构函数将被调用。