[关闭]
@cxm-2016 2016-09-08T01:17:44.000000Z 字数 1827 阅读 1944

C++:类设计要素

c++ no


本节的内容是复习并拓展前面的讨论,已介绍这些原则。[1]

编译器生成的成员函数


1,默认构造函数

默认构造函数要么没有参数,要么全部的参数都有默认值。如果没有定义任何构造函数,编译器将定义默认构造函数,让您能够创建对象。
另外,如果派生类构造函数的成员初始化列表中没有显式的调用基类构造函数,则编译器将使用基类的默认构造函数来构造派生类对象的基类部分。在这种情况下,如果基类没有构造函数,将导致编译错误。

2,复制构造函数

复制构造函数接受其所属的类的对象作为参数。例如,Star类的复制构造函数的原型如下:

  1. Star(const Star &);

在下面情况下,将使用复制构造函数:

3,赋值运算符

默认的复制运算符用于处理同类对象之间的赋值。不要将赋值与初始化混淆了。如果语句创建新的对象,则使用初始化;如果修改已有对象的值,则是赋值:

  1. Star s1;
  2. Star s2 = s1;//初始化
  3. Star s3;
  4. s3 = s1;//赋值

默认赋值为成员赋值。如果成员为类对象,则默认成员赋值将使用相应的赋值运算符。如果需要显式的定义复制构造函数,则基于相同的原因,也需要显式赋值运算符。Star类的赋值运算符的原型如下:

  1. Star & Star::operator=(const Star &);

其他类方法


1,构造函数

构造函数在完成任务前,对象并不存在。

2,析构函数

一定要定义显式析构函数,并完成类对象所需的任何特殊的清理工作。对于类,即使它不需要析构函数,也应该提供一个虚拟析构函数。

3,转换

使用一个参数就可以调用的构造函数定义了从参数类型到类类型的转换。C++11提供了explicit关键字关闭隐式转换。

4,按值传递对象与传递引用

通常,编写使用对象作为参数的函数时,应按照引用而不是按值来传递对象。这样做的原因之一是为了提高效率。按值传递对象涉及到生成临时拷贝,即调用复制构造函数,然后调用析构函数。调用这些函数需要时间,复制大型对象比传递引用话费的时间要多得多。如果函数不修改对象,还应该在参数上声明const。
按引用传递对象的另一个原因是,在继承使用虚函数时,被定义为接受基类引用参数的函数可以接受派生类。

5,返回对象和返回引用

通常,应返回引用而不是返回对象的原因在于,返回对象设计生成返回对象的临时副本,这是调用函数的程序可以使用的副本。因此,返回对象的时间成本包括调用复制构造函数来生成副本所需的时间和调用析构函数删除副本所需的时间。返回引用可以节省时间和内存。
然而,并不总是可以返回引用。函数不能返回在函数中创建的的临时对象的引用,因为当函数结束时,临时对象将会被销毁。因此这种引用是非法的。

5,使用const

使用const时应该特别注意。可以用它来确保方法不会修改参数:

  1. Star::Star(const char * s){...};

可以使用const来确保方法不修改调用它的对象:

  1. void Star::show() const{...};

这里const表示const Star * this;所以当我们返回this引用时,也要加上const

  1. const Star::max(const Star &s) const{
  2. if(s.length>length)
  3. return s;
  4. else
  5. return *this;
  6. }

类函数总结

函数 能否继承 函数类型 默认生成 是否可以是虚函数 是否可以有返回
构造函数 成员
析构函数 成员
= 成员
& 任意
转换函数 成员
() 成员
[] 成员
-> 成员
op= 任意
new 静态成员 void*
delete 静态成员 void*
其他运算符 任意
其他成员 成员
友元 友元

[1] Stephen Prata.C++ Primer Plus.人民邮电出版社.2016.3 523~530
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注