posted @ 2008-05-21 13:59 Zimmem 阅读(2224) 评论(3) 编辑

      今天突然想到,上次提及的构造函数的执行时刻还不够全面。当对象做为参数传入函数时,会不会也引发构造函数的执行?

先试试下面的代码

void FuncA(CParent objTemp)
{
    cout<<"Begin of FuncA"<<endl;
    cout<<"End of FuncA"<<endl;
} 

int main()
{
    cout<<"Begin of main function"<<endl;
    CParent object;
    FuncA(object);
    cout<<"End of main function"<<endl;
    return 0;
}

运行结果如下:

Begin of main function
run constructor of CParent
Begin of FuncA
End of FuncA
run destructor  of CParent
End of main function
run destructor  of CParent
结果很神奇,居然跟我想像的完全不一样,构造函数调用了一次,而析构函数去调用了两次。知道传参的时候是会创建一个临时对象,那么构造函数应该会调用两次才对啊,难道直接把对象传进去不用创建临时对象? 那析构函数又为何调用了两次,没有两个不同的对象,哪来两个对象的析构....
跑去跟细菌讨论了一下,才知道原来还有拷贝构造函数这种东西。
 
在CParent类下添加一个方法如下:
CParent::CParent(const CParent& obj)
{
    cout<<"run the copy destructor of CParent"<<endl;
}
再次运行程序:
Begin of main function
run constructor of CParent
run the copy destructor of CParent
Begin of FuncA
End of FuncA
run destructor  of CParent
End of main function
run destructor  of CParent

结果如预期出现,果真是在传参时调用了拷贝构造函数,重新创建一个临时对象。这时我想,既然是创建了临时对象,那么在函数内部修改了对象属性,对原来的对象有没有影响?于是在类中添加一个属性,修改代码如下:

void FuncA(CParent objTemp)
{
    cout<<"Begin of FuncA"<<endl;
    objTemp.n++;
    cout<<objTemp.n<<endl;
    cout<<"End of FuncA"<<endl;
} 

int main()
{
    cout<<"Begin of main function"<<endl;
    CParent object;
    object.n = 0;
    cout<<object.n<<endl;
    FuncA(object);
    cout<<object.n<<endl;
    cout<<"End of main function"<<endl;
    return 0;
}
运行代码,出现
Begin of main function
run constructor of CParent
0
run the copy destructor of CParent
Begin of FuncA
1807010509
End of FuncA
run destructor  of CParent
0
End of main function
run destructor  of CParent

可以看出,不仅函数内改变临时对象属性并没对原对象产生影响,创建临时对象时也没有复制原对象的属性,使用这种方法传递对象是会出很大问题的。。。

那么有什么方法可以安全传递对象。我想指针是肯定没问题的,先不说,我想试试引用。

先修改代码如下:

void FuncA(CParent& objTemp)
{
    cout<<"Begin of FuncA"<<endl;
    cout<<"End of FuncA"<<endl;
} 

int main()
{
    cout<<"Begin of main function"<<endl;
    CParent object;
    FuncA(object);
    cout<<"End of main function"<<endl;
    return 0;
}

运行结果如下:

Begin of main function
run constructor of CParent
Begin of FuncA
End of FuncA
End of main function
run destructor  of CParent

构造函数跟析构函数都只调用了一次,应该是没有多创建对象了,不过我还是想证明一下。

再次修改代码:

void FuncA(CParent& objTemp)
{
    cout<<"Begin of FuncA"<<endl;
    cout<<&objTemp<<endl;
    cout<<"End of FuncA"<<endl;
} 

int main()
{
    cout<<"Begin of main function"<<endl;
    CParent object;
    cout<<&object<<endl;
    FuncA(object);
    cout<<"End of main function"<<endl;
    return 0;
}

运行一下:

Begin of main function
run constructor of CParent
0013FDDC
Begin of FuncA
0013FDDC
End of FuncA
End of main function
run destructor  of CParent
两个地址一样,那么肯定是同一个对象了。使用引用传递一个对象也是可行的!
posted @ 2008-03-27 02:08 Zimmem 阅读(46) 评论(0)  编辑

       学习编程已快三年,前段时间一直好高鹜远,老想着做一些很牛B的东西。经过两三个项目后,老觉得很飘,没有一种脚踏实地的感觉。现在只想好好地补补基础知识,一切从今天开始。学习的东西记录到这里,方便以后重温。

      类的构造与析构应该是最基础的东西了,可是现在对一些概念还不是很清晰,写了几段代码,证明一下。

      首选定义一个类CParent(以后学习继承还有这个类,所以类名定义成这样),定义如下:

class CParent
{
public:
    CParent(void);
    ~CParent(void);
};
 
很简单的一个类,只有一个构造函数与一个析构函数,两个函数的实现如下:
CParent::CParent(void)
{
    cout<<"run constructor of CParent"<<endl;
}

CParent::~CParent(void)
{
    cout<<"run destructor  of CParent"<<endl;
}

 

建立一个控制台win32程序,实现main函数如下:

#include<iostream>
using namespace std;
#include"Parent.h"

int main()
{
    cout<<"Begin of main function"<<endl;
    cout<<"End of main function"<<endl;
    return 0;
}
 
在不同地方实例化CParent类,看下构造函数与析构函数何时执行。
 
首先在main函数中建立CParent类
int main()
{
    cout<<"Begin of main function"<<endl;
    CParent Object;
    cout<<"End of main function"<<endl;
    return 0;
}

程序运行结果如下:

Begin of main function
run constructor of CParent
End of main function
run destructor  of CParent
可以看出,构造函数在main内部创建对象时执行,析构函数要等到main函数结束自动执行。
 
下面看看在其它函数内部创建CParent对象时,又是什么情况
新添一个函数FuncA(),同时修改main函数,代码如下。
void FuncA()
{
    cout<<"Begin of FuncA"<<endl;
    CParent Object;
    cout<<"End of FuncA"<<endl;
}

int main()
{
    cout<<"Begin of main function"<<endl;
    FuncA();
    cout<<"End of main function"<<endl;
    return 0;
}

程序运行结果如下:

Begin of main function
Begin of FuncA
run constructor of CParent
End of FuncA
run destructor  of CParent
End of main function

构造函数创建对象时执行,析构函数在FuncA结束后,返回main函数之前执行。

如果是定义一个全局变量的对象呢?代码如下:

CParent object;

int main()
{
    cout<<"Begin of main function"<<endl;
    cout<<"End of main function"<<endl;
    return 0;
}

运行结果:

run constructor of CParent
Begin of main function
End of main function
run destructor  of CParent

如果是用new呢?

int main()
{
    cout<<"Begin of main function"<<endl;
    CParent *p=new CParent();
    cout<<"End of main function"<<endl;
    return 0;
}

运行结果:

Begin of main function
run constructor of CParent
End of main function
可以看出,定义全局变量,及使用new 关键字创建对象,虽然对象都是存储在堆上,但创建全局变量的方法最后程序会把对象销废,而使用new关键字却不会。
posted @ 2008-03-25 19:42 Zimmem 阅读(88) 评论(0)  编辑