1. 在类内部定义的函数默认为inline类型的
2. 类的有些成员必须在构造函数初始化列表中进行初始化。对于这样的成员, 在构造函数函数体中对他们赋值不起作用。这样类型的成员有:没有默认构造函数的类类型的成员, const或引用类型的成员(不管他们本身是什么类型的,如int &a或是string &a), 都必须在构造函数初始化列表中进行初始化。如下例:
3. 关于类成员被初始化的次序:
构造函数初始化列表仅用于初始化成员的值, 并不指定这些初始化执行的次序。成员被初始化的次序就是定义成员的次序。如下例:
以上程序在初始化成员时, 并不是按照初始化列表的次序先初始化m_i, 然后m_j, 而是按照这两个成员定义时的次序, 先初始化m_j, 在m_i, 于是出现了问题, 在初始化列表中m_j(m_i), 也就是想用m_i去初始化m_j ,但这是m_i还没有被初始化, 所以会出现编译错误…
C++ primer中推荐:最好按照与成员声明一致的次序编写初始化列表。而且, 尽可能的避免使用类成员去初始化其他类成员。
4. 如果为类定义了其他的构造函数, 则提供一个默认的构造函数( 无参)几乎总是对的。通常, 在默认构造函数中给成员提供的初始值应该指出该对象是”空”的。
关于编译器提供的默认的构造函数对类成员初始化遵循以下规则, 具有类类型的成员通过运行各自的默认构造函数进行初始化, 内置和复合类型的成员, 如指针和数组, 只对定义在全局作用域中的对象才初始化, 当对象定义在局部作用域时, 内置的或复合类型的成员不进行初始化。所以当类具有内置的或符合类型的成员是, 应该提供自定义的构造函数来初始化这些成员。
当一个类没有提供默认的构造函数时,它将失去以下功能:
(1) 不能用作动态分配数组的元素类型
(2) 静态定义的数组必须为每个元素提供一个显示的初始化式。
(3) 当将这个类型的对象放到诸如vector等的容器中时, 不能只定义容器的大小而不提供元素的初始化式的构造函数。
5.关于构造函数定义的隐式转换
如:
类Test的display()函数需要一个Try类的对象, 单是当我们传给他一个cin时, 编译也能够通过, 这中间编译器给我们做了隐式的转换, 通过Try的构造函数Try(istream &is)进行了转换, 有时这种转换不是必须的, 我们可以在声明构造函数时前面加上关键字explicit来切断这种隐式转换。
如:
这时在调用test.display()时必须显示的构造Try的对象了, test.display(Try(cin));
推荐:通常情况下, 要将单个形参的构造函数设置为explicit, 防止发生隐式的转换, 造成不必要的错误. Explicit关键字只能用于类内部定义的构造函数声明上, 在类外部定义上不用。
6. 当我们将其他类的成员函数声明为友元函数时, 必须使用该函数所属的类名字加以限定, 如:
7. 一些标记成员函数特殊类型的关键字:
Inline:可以放在声明处, 也可以放在定义处
Static:放在声明处, 无需放在定义处(在类内部定义除外, 数据成员也是如此, 只需在声明处使用static, 定义处不能使用)
Explicit:放在声明处,不能放在定义处(在类内部定义的除外)
Const:声明处, 定义处都要有。
Friend: 放在声明处, 无需放在定义处(在类内部定义除外)
如:
8. const static数据成员在类的定义体中初始化时, 该数据成员仍需要在类的定义体外进行定义, 如:
C++ primer上说const static类型的数据成员即使在类定义内部进行了初始化, 还是需要在类定义外部定义这个数据成员也就是上面的const int Try::MAX;句, 但是好像把这句去了编译也没问题…
9.static类型成员不是类对象的组成部分, 所以static数据成员的类型可以是该成员所属的类类型, 而非static成员只能是改成员所属类类型的指针或引用. 如: