声明:
- 文中内容收集整理自《Effective C++(中文版)第三版》,版权归原书所有。
- 本内容在作者现有能力的基础上有所删减,另加入部分作者自己的理解,有纰漏之处敬请指正。
条款19:设计class犹如设计type
Treat class design as type design.
class侧重于自定义的类,而type侧重于系统预定义的类。当你定义了一个新class,也就定义了一个新type。因此应该带着和“语言设计者当初设计语言内置类型时“一样的谨慎来研讨class的设计。
那么如何设计高效的classes呢?
1. 新type的对象该如何被创建和销毁?
这涉及到构造函数和析构函数以及内存分配函数和释放函数new、new[]、delete和delete[]。
2. 对象初始化与对象的赋值应该有什么样的差别?
这涉及到构造函数和赋值操作符的行为,另外注意“初始化”和“赋值”的区别,它们对应于不同的函数调用。
3. 新type的对象如果被pass-by-value意味着什么?
这涉及到拷贝构造函数。
4. 什么是新type的合法值?
对象的成员变量通常只有某些数值集是有效的。
5. 你的新type需要配合某个继承图系吗?
要判断自己设计的class是否需要继承或被继承。如果你允许其他classes继承自你的class,那会影响你生命的函数——尤其是析构函数是否为virtual。
6. 你的新type需要什么样的转换?
主要涉及到隐式转换,如果你希望允许类型T1之物被隐式转换为类型T2,就必须在class T1内写一个类型转换函数(operator T2)或在class T2内写一个non-explicit-one-argument(可被单一实参调用)的构造函数。
类型转换函数的一般形式为:
operator T2()
{
//实现转换的语句
}
//考虑这个用于字体的RAII
FontHandle getFont(); //C API
void releaseFont(FontHandle fh); //C API
class Font
{
public:
explicit Font(FontHandle fh) f(fh)
{ }
~Font()
{
releaseFont(f); //释放资源
}
//隐式转换函数,将Font转换为FontHandle
operator FontHandle() const
{
return f;
}
private:
FontHandle f; //原始(raw)字体资源
}
转换函数有以下性质:
- 转换函数必须是类的成员函数
- 转换函数不能声明返回类型
- 形参列表必须为空
- 类型转换函数通常应该是
const
7. 什么样的操作符和函数对此新type而言是合理的?
8. 什么样的标准函数应该驳回?
即哪些成员声明为private。
9. 谁该取用新type成员?
即类的封装问题,一些而言,成员变量都应该是private的,而在public函数里面提供对这些成员变量的访问get和set函数。如果需要的话,可以使用友元,但友元也要慎用。
10. 什么是新type的未声明接口?
11. 你的新type有多么一般化?
这涉及到泛型编程。
12. 你真的需要一个新type吗?
请记住:
class的设计就是type的设计。在定义一个新type之前,请确定你已经考虑过本条款覆盖的所有主题。