龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > C/C++开发 >

精品文章 论C++构造函数中的不合理设计(1)(2)

时间:2011-04-12 23:18来源:未知 作者:admin 点击:
分享到:
构造函数的类型 C++中构造函数有许多种类型,最常用的式缺省构造函数和拷贝构造函数,也存在一些不常用的构造函数。下面介绍了四种不同的构造函数

构造函数的类型

C++中构造函数有许多种类型,最常用的式缺省构造函数和拷贝构造函数,也存在一些不常用的构造函数。下面介绍了四种不同的构造函数。

1、缺省构造函数

缺省构造函数是没有参数的函数。另外,缺省构造函数也可以在参数列表中以参数缺省值的方式声明。缺省构造函数的作用是把对象初始化为缺省的状态。如果在类中没有显式定义构造函数,那么编译器会自动的隐式创建一个,这个隐式创建的构造函数和一个空的构造函数很相像。他除了产生对象的实例以外什么工作都不做。在许多情况下,缺省构造函数都会被自动的调用,例如在一个对象被声明的时候,就会引起缺省构造函数的调用。

2、拷贝构造函数

拷贝构造函数,经常被称作X(X&),是一种特殊的构造函数,他由编译器调用来完成一些基于同一类的其他对象的构件及初始化。它的唯一的一个参数(对象的引用)是不可变的(因为是const型的)。这个函数经常用在函数调用期间于用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。

在C++中,下面三种对象需要拷贝的情况。因此,拷贝构造函数将会被调用。

1). 一个对象以值传递的方式传入函数体

2). 一个对象以值传递的方式从函数返回

3). 一个对象需要通过另外一个对象进行初始化

以上的情况需要拷贝构造函数的调用。如果在前两种情况不使用拷贝构造函数的时候,就会导致一个指针指向已经被删除的内存空间。对于第三种情况来说,初始化和赋值的不同含义是构造函数调用的原因。事实上,拷贝构造函数是由普通构造函数和赋值操作赋共同实现的。描述拷贝构造函数和赋值运算符的异同的参考资料有很多。

拷贝构造函数不可以改变它所引用的对象,其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环。

除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。换句话说,你从函数返回得到的只是对象的一份拷贝。但是同样的,拷贝构造函数被正确的调用了,你不必担心。

如果在类中没有显式的声明一个拷贝构造函数,那么,编译器会私下里为你制定一个函数来进行对象之间的位拷贝(bitwise copy)。这个隐含的拷贝构造函数简单的关联了所有的类成员。许多作者都会提及这个默认的拷贝构造函数。注意到这个隐式的拷贝构造函数和显式声明的拷贝构造函数的不同在于对于成员的关联方式。显式声明的拷贝构造函数关联的只是被实例化的类成员的缺省构造函数除非另外一个构造函数在类初始化或者在构造列表的时候被调用。

拷贝构造函数是程序更加有效率,因为它不用再构造一个对象的时候改变构造函数的参数列表。设计拷贝构造函数是一个良好的风格,即使是编译系统提供的帮助你申请内存默认拷贝构造函数。事实上,默认拷贝构造函数可以应付许多情况。

3、用户定义的构造函数

用户定义的构造函数允许对象在被定义的时候同时被初始化。这种构造函数可以有任何类型的参数。一个用户定义的和其它类型的构造函数在类 mystring 中得以体现:

  1. class mystring   
  2. {......  
  3. public: mystring(); // Default constructor  
  4. mystring (mystring &src)  
  5. // Copy constructor  
  6. mystring (char * scr);  
  7. // Coercion constructor  
  8. mystring ( char scr[ ], size_t len);  
  9. // User-Defined constructor  
  10. }; 

4、强制构造函数

C++中,可以声明一个只有一个参数的构造函数来进行类型转换。强制构造函数定一个从参数类型进行的一个类型转换(隐式的或显式的)。换句话说,编译器可以用任何参数的实例来调用构造函数。这样做的目的是建立一个临时实例来替换一个参数类型的实例。注意标准新近加入C++的关键字explicit 是用来禁止隐式的类型转换。然而,这一特性还没能被所有的编译器支持。下面是一个强制构造函数的例子:

  1. class A   
  2. {  
  3. public :  
  4. A(int ){ }  
  5. };  
  6. void f(A) { }   
  7. void g()  
  8. {  
  9. A My_Object= 17;  
  10. A a2 = A(57);  
  11. A a3(64);  
  12. My_Object = 67;  
  13. f(77);  
  14. };  

像A My_Object= 17;这种声明意味着A(int)构造函数被调用来从整型变量生成一个对象。这样的构造函数就是强制构造函数。


精彩图集

赞助商链接