没有合适的资源?快使用搜索试试~ 我知道了~
第9章类的构造函数、析构函数与赋值函数[文].pdf
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 136 浏览量
2021-10-12
05:42:53
上传
评论
收藏 20KB PDF 举报
温馨提示
试读
11页
第9章类的构造函数、析构函数与赋值函数[文].pdf
资源推荐
资源详情
资源评论
构造函数、 析构函数与赋值函数是每个类最基本的函数。 它们太普通以致让人容易麻痹大意,
其实这些貌似简单的函数就象没有顶盖的下水道那样危险。
每个类只有一个析构函数和一个赋值函数, 但可以有多个构造函数 (包含一个拷贝构造函数,
其它的称为普通构造函数) 。对于任意一个类 A,如果不想编写上述函数, C++编译器将自动
为 A产生四个缺省的函数,如
A(void); // 缺省的无参数构造函数
A(const A &a); // 缺省的拷贝构造函数
~A(void); // 缺省的析构函数
A & operate =(const A &a); // 缺省的赋值函数
这不禁让人疑惑,既然能自动生成函数,为什么还要程序员编写?
原因如下:
(1)如果使用“缺省的无参数构造函数”和“缺省的析构函数” ,等于放弃了自主“初始化”
和“清除”的机会, C++发明人 Stroustrup 的好心好意白费了。
(2)“缺省的拷贝构造函数”和“缺省的赋值函数”均采用“位拷贝”而非“值拷贝”的方
式来实现,倘若类中含有指针变量,这两个函数注定将出错。
对于那些没有吃够苦头的 C++程序员, 如果他说编写构造函数、 析构函数与赋值函数很容易,
可以不用动脑筋,表明他的认识还比较肤浅,水平有待于提高。
本章以类 String 的设计与实现为例,深入阐述被很多教科书忽视了的道理。 String 的结构
如下:
class String
{
public:
String(const char *str = NULL); // 普通构造函数
String(const String &other); // 拷贝构造函数
~ String(void); // 析构函数
String & operate =(const String &other); // 赋值函数
private:
char *m_data; // 用于保存字符串
};
9.1 构造函数与析构函数的起源
作为比 C 更先进的语言, C++提供了更好的机制来增强程序的安全性。 C++编译器具有严格的
类型安全检查功能,它几乎能找出程序中所有的语法问题,这的确帮了程序员的大忙。但是
程序通过了编译检查并不表示错误已经不存在了,在“错误”的大家庭里, “语法错误”的地
位只能算是小弟弟。级别高的错误通常隐藏得很深,就象狡猾的罪犯,想逮住他可不容易。
根据经验,不少难以察觉的程序错误是由于变量没有被正确初始化或清除造成的,而初始化
和清除工作很容易被人遗忘。 Stroustrup 在设计 C++语言时充分考虑了这个问题并很好地予
以解决:把对象的初始化工作放在构造函数中,把清除工作放在析构函数中。当对象被创建
时,构造函数被自动执行。当对象消亡时,析构函数被自动执行。这下就不用担心忘了对象
的初始化和清除工作。
构造函数与析构函数的名字不能随便起, 必须让编译器认得出才可以被自动执行。 Stroustrup
的命名方法既简单又合理:让构造函数、析构函数与类同名,由于析构函数的目的与构造函
数的相反,就加前缀‘ ~’以示区别。
除了名字外,构造函数与析构函数的另一个特别之处是没有返回值类型,这与返回值类型为
void 的函数不同。构造函数与析构函数的使命非常明确,就象出生与死亡,光溜溜地来光溜
溜地去。如果它们有返回值类型,那么编译器将不知所措。为了防止节外生枝,干脆规定没
有返回值类型。 (以上典故参考了文献 [Eekel, p55-p56] )
9.2 构造函数的初始化表
构造函数有个特殊的初始化方式叫“初始化表达式表” (简称初始化表) 。初始化表位于函数
参数表之后,却在函数体 {} 之前。这说明该表里的初始化工作发生在函数体内的任何代码
被执行之前。
构造函数初始化表的使用规则:
u 如果类存在继承关系,派生类必须在其初始化表里调用基类的构造函数。
例如
class A
{ ,
A(int x); // A 的构造函数
};
class B : public A
{ ,
B(int x, int y);// B 的构造函数
};
B::B(int x, int y)
: A(x) // 在初始化表里调用 A 的构造函数
{
,
}
u 类的 const 常量只能在初始化表里被初始化,因为它不能在函数体内用赋值的方式来初始
化(参见 5.4 节)。
u 类的数据成员的初始化可以采用初始化表或函数体内赋值两种方式,这两种方式的效率不
完全相同。
非内部数据类型的成员对象应当采用第一种方式初始化,以获取更高的效率。例如
class A
{ ,
A(void); // 无参数构造函数
A(const A &other); // 拷贝构造函数
A & operate =( const A &other); // 赋值函数
} ;
剩余10页未读,继续阅读
资源评论
czq131452007
- 粉丝: 2
- 资源: 12万+
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功