首页 > 代码库 > C++类设计过程中的原则(总结)

C++类设计过程中的原则(总结)

一、由编译器生成的成员函数

1)默认的构造函数

默认构造函数定义为没有参数,或者有默认的参数值。当用户自己未定义时,系统可以提供。

自动生成的默认构造函数,会调用继承的基类的默认构造函数来构造派生类的基类部分。

若Star是一个类,则

Star orig;

Star array[6];都将需要默认构造函数。

如果自己定义了构造函数,则系统不会再生成默认构造函数,这个时候最好自己要定义一个默认构造函数。

构造函数 -- 【确保对象的生成】 -- 最好提供显式的默认构造函数,以确保对象能够正确的初始化为合理值。

2)复制构造函数

Star类的复制构造函数圆形如下:

Star(const Star &)

通常,我们会在一下情况下用到复制构造函数:

* 将新对象初始化为一个同类对象

* 函数按值传递对象参数

* 函数返回对象(而不是对象的引用)

* 生成临时对象

如果自己没有显式的定义复制构造函数,编译器将会自动生成一个其原型(但不提供函数定义??),以使得新对象的的每个成员初始化为原始对象相应的成员。

但是,当出现需要深度复制的情况时(使用new构造成员),或者需要修改的静态变量,这个时候一定要自己定义复制构造函数!!

例如:

string(const string & s)

{

// new char []

}

3)赋值运算符

在同类对象之间进行赋值操作,但不要把赋值和复制初始化混淆!!

【如果语句创建新对象,一般是复制初始化构造;语句修改已有对象,则是赋值】

Star orig;

Star pre = orig;// copy ctor

Star post;

post = pre;// copy assignment

赋值运算符返回对象的引用(使得可以连续赋值)。

orig = pre = post; 

这是string类的赋值运算符重载:(见《C++ string类字符串的常用操作及实现》,同时实现“自我赋值”和"异常安全处理"

string & string::operator=(const string &) const ;


二、类设计的其它注意事项

1)构造函数不能够被继承(使用),只有自己需要生成对象时被使用。继承的派生类构造函数,会调用基类的构造函数。

2)析构函数,在使用new动态生成成员变量是一定要显式定义析构函数;当基类中存在virtual或者pure virtual时,将析构函数也定义为virtual。

3)转换构造函数,如果你不希望出现隐式的类型转换,使用【explicit】声明函数,但仍然可以使用显式的强制转换。

例如:

explict string(const char *);

4)按值传递和按引用传递

我们知道,一般情况下在类设计中都是用按引用传递,按值传递会隐式的调用复制构造函数和析构函数,在返回大型类时极其影响效率。可以节省时间和内存!!

按引用传递的另外原因:在继承使用虚函数时,被定义接受基类引用的参数可以接受派生类的引用。

5)const的使用

尽可能的使用const,但要注意场合。确保const参数在传递过程中不会修改其属性(常量),【可以将非const传给const参数,但禁止将const传给非const】


三、共有继承的注意事项

1)IS-A关系式典型的基类 - 派生(is a king of),HAS-A有种接口的赶脚,接口的实现(is implemented as a),用友元函数实现(uses a)。纯自己的感觉,有误请指正。

2)基类的构造函数、析构函数和(一般情况下)赋值函数都不能继承。可以将派生类赋值给基类,反过来则maybe。

3)对于公共用户,使用保护成员和私有成员一样;对于派生类而言,使用保护乘员和公有成员一样。

派生类可以直接访问保护乘员,但只能通过基类的共有方法访问私有成员,相对来讲私有成员具有更好的安全性。

保护成员则可以简化编码,提高访问速度,但是这会使得派生类直接访问和修改基类的保护成员。

【使用私有成员比保护成员更好(尽可能的使用),但是保护方法很有用】

4)虚方法

设计基类时将方法定义为虚,使得【多态】派生类能够重新定义方法,这样可以使用【动态联编】。

纯虚函数使得类ABC【只定义接口,不涉及实现】,不能生成真正的对象。

5)友元函数

友元函数不是类的方法,因此不能够继承,在派生类中需要重新定义。

如果要使用基类的friend 函数,一般我们会使用【强制转换】,将派生类的指针或者引用转换成基类的指针或引用



 -- 【C++ Primer Plus】温习小结。