C++中类的设计和实现

0. 一个实体应该有一个紧凑的职责;用小类代替巨类;用组合代替继承;优先编写非成员非友员函数(<<,>>,+,*等)

1. 对于值类(如std::pair,std::vector),模仿内置类型:
    有一个public析构函数,复制构造函数和带有语义的赋值操作符;
    没有虚拟函数;
    用做具体类,不用作基类;
    总是在栈中实例化,或者作为另一个类直接包含的成员实例化。

   对于基类:
   有一个pulic的虚拟析构函数,或者protected的非虚拟析构函数;
   非public的拷贝构造函数和赋值操作符;
   总是动态在堆中实例化为具体派生类对象,并通过一个(智能)指针来使用。

2. C++对象的初始化顺序
   虚基类按深度优先、从左到右的顺序初始化;
   基类按在类中声明的顺序初始化;
   成员对象按声明的顺序初始化;
   自身的构造函数。

3. 关于封装
   除了C风格的struct,将所有成员变量声明为private;
   对于本应该为protected的成员变量,声明为private,并用protected函数返回引用,这样可以增加可扩展性;
   接口是最需要在第一时间作对的事情,其他都可以在后期进行修正。

   不要公开内部数据;

4. 关于继承

   通过public inheritance模塑出“isa”关系;通过private 继承实现is implemented in terms of关系,并可以调用父类的protected函数。
   对于public继承,纯虚函数意味着接口继承;虚函数意味着接口和默认实现继承;非虚拟函数意味着接口和实现都被继承,“不变形凌驾于变异性之上”

   绝对不要重新定义继承而来的非虚拟函数(非虚拟函数是静态绑定)
   绝对不要重新定义继承而来的虚拟函数的缺省函数值(缺省函数值为静态绑定)
   避免在继承体系中做向下转型动作(重新设计类的层次)

4. 关于虚拟
   尽量利用非虚接口模式(Nonvirtual Interface)让接口函数成为非虚的;
   尽量让虚函数成为private;如果子类需要调用父类虚函数的实现,声明为protected;
   基类的析构函数要么为公用虚函数,要么为保护非虚函数。

5. 注意问题

   不要提供隐式转换(隐式转换构造函数和转换操作符),为单参数构造函数加上explicit,提供转换函数代替转换操作符。隐式转换构造函数:能够有一个参数调用而且未声明为explicit的构造函数;转换操作符:operator const char*()

   避免在构造函数和析构函数中调用虚拟函数。(因为对象还没有创建完成或者正在销毁,会导致未定义的行为);

   避免从并非要设计成基类的类中继承;要添加行为,应该使用非成员函数;要添加状态,要使用组合。

   如果class内动态分配内存,请为此class声明一个copy constructor和一个assignment运算符(内存分配问题)

   initialization list中的members初始化次序应该和其在class内的声明次序相同(class members按照声明顺序来初始化)

   令operation=传回"*this 的 reference"

   在operation=中为所有的data members设定内容(主要是base class部分,拷贝构造函数也要注意这个问题)

   在operation=中检查是否“自己赋值给自己”(动态内存问题)

你可能感兴趣的:(C++,Class,inheritance,reference,Constructor,initialization)