===============================================
未完待续,转载时请表明出处:[url]http://www.cofftech.com/thread-1395-1-1.html[/url]
欢迎大家跟帖讨论哈~~~~~
===============================================
用户所定义的析构函数主要用于释放在建立对象时构造函数从堆区中分配的空间。
和构造函数相同,只当用户在类中定义了析构函数后,程序删除对象时系统才调用析构函数。
析构函数是类的特殊成员函数,它的名字也与类名相同,只是在前面加一个符号“~”。析构函数没有任何参数,也不返回任何值。
[例1]析构函数的用途
#include <string.h>
#include <iostream.h>
class string
{
char *contents;
int size;
public:
string(int sz) {
size = sz;
contents = new char[sz];
cout<<"constructor "<<size<<endl; }
~string() { delete [ ]contents;
cout<<"destructor "<<size<<endl; }
};
void main( )
{
string s1(10), s2(20);
}
/* Results:
constructor 10
constructor 20
destructor 20
destructor 10 */
以上程序中,建立对象时系统调用构造函数,在堆区内分配了一定空间;程序结束时系统删除对象,自动调用析构函数,将所分配的空间释放,退还给堆区。
从以上程序还可看出:
析构函数的调用顺序正好与构造函数的调用顺序相反。
前面提到,如已定义析构函数,则删除对象时将自动调用析构函数,因此,如对象是在一个函数或一个程序块内建立的,则在退出该函数或程序块时,将会删除该对象,从而自动地调用析构函数,见下例。
[例2] 退出程序块和函数时都删除对象,因而都调用析构函数
#include <iostream.h>
class point {
int j;
public:
point ( int i ) { j = i;
cout<<"Cons"<<j<<endl; }
~point ( ) { cout<<"Des"<<j<<endl; }
};
void main()
{
point objm(1);
{ //为教学目的而设的程序块
point objb(2);
cout<<"end of block"<<endl;
}
cout<<"end of program!"<<endl;
}
/* Results:
Cons1
Cons2
end of block
Des2
end of program!
Des1 */
还须指出,有时用户不在类中定义构造函数,但却定义了析构函数。虽然程序建立对象时系统并不调用构造函数;但在程序结束时系统自动删除对象,就会调用析构函数。
现在利用析构函数来再次了“按数值调用”和“按引用调用”时形参的不同处理方式。
在阅读下列程序之前,先熟悉一下对象用作形参和返回值的格式。我们已熟悉:
int fun( int i )
{
return i;
} 的形式。
但不熟悉:
AA fun( AA obj )
{
return obj;
} 的形式。
将两者对比一下,就容易看出,前例中形参是预定义类型int变量i,而后例中形参是class AA的对象obj。
函数调用方式,其中“按数值调用”方式将实参复制为副本并将其推入堆栈,而“按引用调用”方式则不复制实参而只将实参的指针(即地址)复制为副本并将其推入堆栈。 如果其实参是类的对象,则“按数值调用”方式将建立新的临时对象并将其推入堆栈,而“按引用调用”方式则只复制对象的指针。这点可从以下程序看出。
[例3] // destructor_3.cpp
// To differentiate between two modes: "call-by-value" and "call-by-reference"
#include <iostream.h>
class AA {
public:
int a;
AA (int x) { a = x;
cout<<"Cons-"<<a<<endl; }
~AA ( )
{ cout<<"Des-"<<a<<endl; }
};
void inc_by_value(AA obj) //形参是class AA的对象obj
{
obj.a++;
cout<<"program inc_by_value ended!"<<endl;
}
void inc_by_refer(AA & obj) //形参是class AA的对象obj的引用,实即指针
{
obj.a++;
}
void main()
{
AA obj(10);
inc_by_value(obj);
cout<<"call_by_value:a="<<obj.a<<endl;
obj.a = 20;
inc_by_refer(obj);
cout<<"call_by_reference:a="<<obj.a<<endl;
cout<<"program main ended!"<<endl;
}
/* Results:
Cons-10
program inc_by_value ended!
Des-11
call_by_value:a=10
call_by_reference:a=21
program main ended!
Des-21
*/
以上程序中定义了构造函数和析构函数。在“按数值调用”中,由系统为实参(class AA的对象)在堆栈上产生副本(也即建立新的临时对象并复制所有非静态数据),并不调用构造函数。当对函数inc_by_value( )的调用结束时,对象副本(即临时对象)被删除,从堆栈中消失,因而它的析构函数被立即调用。
而在“按引用调用”中,引用作为“别名其表,指针其实”,实参不需要产生对象副本而只产生指针副本(也即不建立临时对象)。因此在调用函数inc_by_refer( )时不须要建立临时对象,在退出函数时也不删除任何对象,也就不会调用析构函数,这种调用方式减少了空间和时间上的开销。
未完待续,转载时请表明出处:[url]http://www.cofftech.com/thread-1395-1-1.html[/url]
欢迎大家跟帖讨论哈~~~~~
===============================================
用户所定义的析构函数主要用于释放在建立对象时构造函数从堆区中分配的空间。
和构造函数相同,只当用户在类中定义了析构函数后,程序删除对象时系统才调用析构函数。
析构函数是类的特殊成员函数,它的名字也与类名相同,只是在前面加一个符号“~”。析构函数没有任何参数,也不返回任何值。
[例1]析构函数的用途
#include <string.h>
#include <iostream.h>
class string
{
char *contents;
int size;
public:
string(int sz) {
size = sz;
contents = new char[sz];
cout<<"constructor "<<size<<endl; }
~string() { delete [ ]contents;
cout<<"destructor "<<size<<endl; }
};
void main( )
{
string s1(10), s2(20);
}
/* Results:
constructor 10
constructor 20
destructor 20
destructor 10 */
以上程序中,建立对象时系统调用构造函数,在堆区内分配了一定空间;程序结束时系统删除对象,自动调用析构函数,将所分配的空间释放,退还给堆区。
从以上程序还可看出:
析构函数的调用顺序正好与构造函数的调用顺序相反。
前面提到,如已定义析构函数,则删除对象时将自动调用析构函数,因此,如对象是在一个函数或一个程序块内建立的,则在退出该函数或程序块时,将会删除该对象,从而自动地调用析构函数,见下例。
[例2] 退出程序块和函数时都删除对象,因而都调用析构函数
#include <iostream.h>
class point {
int j;
public:
point ( int i ) { j = i;
cout<<"Cons"<<j<<endl; }
~point ( ) { cout<<"Des"<<j<<endl; }
};
void main()
{
point objm(1);
{ //为教学目的而设的程序块
point objb(2);
cout<<"end of block"<<endl;
}
cout<<"end of program!"<<endl;
}
/* Results:
Cons1
Cons2
end of block
Des2
end of program!
Des1 */
还须指出,有时用户不在类中定义构造函数,但却定义了析构函数。虽然程序建立对象时系统并不调用构造函数;但在程序结束时系统自动删除对象,就会调用析构函数。
现在利用析构函数来再次了“按数值调用”和“按引用调用”时形参的不同处理方式。
在阅读下列程序之前,先熟悉一下对象用作形参和返回值的格式。我们已熟悉:
int fun( int i )
{
return i;
} 的形式。
但不熟悉:
AA fun( AA obj )
{
return obj;
} 的形式。
将两者对比一下,就容易看出,前例中形参是预定义类型int变量i,而后例中形参是class AA的对象obj。
函数调用方式,其中“按数值调用”方式将实参复制为副本并将其推入堆栈,而“按引用调用”方式则不复制实参而只将实参的指针(即地址)复制为副本并将其推入堆栈。 如果其实参是类的对象,则“按数值调用”方式将建立新的临时对象并将其推入堆栈,而“按引用调用”方式则只复制对象的指针。这点可从以下程序看出。
[例3] // destructor_3.cpp
// To differentiate between two modes: "call-by-value" and "call-by-reference"
#include <iostream.h>
class AA {
public:
int a;
AA (int x) { a = x;
cout<<"Cons-"<<a<<endl; }
~AA ( )
{ cout<<"Des-"<<a<<endl; }
};
void inc_by_value(AA obj) //形参是class AA的对象obj
{
obj.a++;
cout<<"program inc_by_value ended!"<<endl;
}
void inc_by_refer(AA & obj) //形参是class AA的对象obj的引用,实即指针
{
obj.a++;
}
void main()
{
AA obj(10);
inc_by_value(obj);
cout<<"call_by_value:a="<<obj.a<<endl;
obj.a = 20;
inc_by_refer(obj);
cout<<"call_by_reference:a="<<obj.a<<endl;
cout<<"program main ended!"<<endl;
}
/* Results:
Cons-10
program inc_by_value ended!
Des-11
call_by_value:a=10
call_by_reference:a=21
program main ended!
Des-21
*/
以上程序中定义了构造函数和析构函数。在“按数值调用”中,由系统为实参(class AA的对象)在堆栈上产生副本(也即建立新的临时对象并复制所有非静态数据),并不调用构造函数。当对函数inc_by_value( )的调用结束时,对象副本(即临时对象)被删除,从堆栈中消失,因而它的析构函数被立即调用。
而在“按引用调用”中,引用作为“别名其表,指针其实”,实参不需要产生对象副本而只产生指针副本(也即不建立临时对象)。因此在调用函数inc_by_refer( )时不须要建立临时对象,在退出函数时也不删除任何对象,也就不会调用析构函数,这种调用方式减少了空间和时间上的开销。