Ⅰ、有时不得不用到“构造函数初始值列表”,原因是有些编译器不支持类内初始值,这样做可以避免在函数体内初始化。
需要注意的是:被初始化列表忽略的数据成员将被默认初始化(结果取决于位置,可能产生可怕后果)。下面是构造器的 N 种情况:
- 程序员直接忽略构造器 --> 产生默认合成的构造函数 --> 成员被默认初始化 --> 不确定的结果。
- 给数据成员提供初始值(Java 中所谓的属性初始化),不写构造函数 --> 默认合成的构造函数使用提供的初始值初始化对应的成员 --> 被忽略的成员被默认初始化。
- 不使用类内初始值,而采用构造函数初始值列表 --> 被忽略的成员被默认初始化。、
- ·····
记一下比较好的实践:提供类内初始值 + 显示地初始化没有类内初始值的每个成员。
总结起来就是:确保每个成员在创建后都有一个确定的值,但是又不要重复初始化(重复初始化:类内初始值与构造函数赋值相同)。
Ⅱ、拷贝、赋值、析构也是有合成版本的!
如果没写的话,编译器都会替我们做,但是某些情形我们不能依赖合成的版本:
那就是 - 管 - 理 - 动 - 态 - 内 - 存 的类!!!( 包含 string 和 vector 的类除外)
方法论总结:
- 通常情况下都不需要手动去写。
- 在合适的情况下,尽可能用 string 和 vector 来动态分配内存!
Ⅲ、友元函数需要在类外部再专门进行一次声明。举例:
class.h
#ifndef CLASS_H_INCLUDED #define CLASS_H_INCLUDED class Person { friend int getNo(const Person&); private: int no = 48; }; int getNo(const Person&); // necessary #endif
class.cpp
#include "class.h" int getNo(const Person& x) { return x.no; }
main.cpp
#include "class.h" #include <stdio.h> int main() { Person p; printf("%d ", getNo(p)); return 0; }
运行结果:
root@iZwz9f8i2ttdoht64eezprZ:~/cprg# g++ -std=c++11 main.cpp class.cpp root@iZwz9f8i2ttdoht64eezprZ:~/cprg# ./a.out 48
相关阅读: