一、关于创造对象的时候初始值,对象的初始化值到底是多少,这个得看对象创造的是在哪里创造,假如没有对创建的对象进行初始化,那么它的初始值是多少呢?
(1)假如是在静态存储区,那么就为0。
(2)假如是在栈上,或者是堆上,那么就为随机值
二、在生活中,对象都是初始化了之后才上市的,那么问题就来了,程序如何对一个对象进行初始化,下面给出两种解决方案。
(1)在类中提供一个public的initialize函数,创造对象后立即调用initialize函数进行初始化。下面是示例:
(2)但是这一种方式存在一定的问题,initialize只是一个普通的函数,使用这一种方式的话,必须显示调用initialize函数,假如不调用initialize函数,运行的结果也是不确定的。在c++中可以定义与类名相同的特殊成员函数,这种成员函数叫构造函数。
注意:每个对象在使用之前都应该初始化;类的构造函数用于对象的初始化;
构造函数与类同名并没有返回值;构造函数在对象定义时自动被调用。
三、两个特殊的构造函数
无参构造函数:
在当类中没有定义构造函数的时候,编译器默认提供一个无参构造函数,而且函数体为空滴。
拷贝构造函数(也可以理解为有参构造函数):
在当类中没有定义拷贝构造函数的时候,编译器默认提供一个拷贝构造函数,简单的进行成员变量值得复制。
但是拷贝构造函数也分为浅拷贝和深拷贝
浅拷贝:拷贝后的物理状态相同
深拷贝:拷贝后对象的逻辑状态相同
(注意:编译器提供)
思考一个问题:什么时候需要进行深拷贝呢?
对象中有成员指代了系统资源
成员指向了动态内存的空间
成员打开了外存中的文件
成员使用了系统中的网络端口
总结:
下面以:开发一个数组类解决原生数组的安全性问题为例解说一下深度拷贝
IntArray.h:
class IntArray
{
private:
int m_length;
int* m_pointer;
public:
IntArray(int len);
IntArray(const IntArray& obj);
int length();
bool get(int index, int& value);
bool set(int index ,int value);
void free();
};
IntArray.cpp:
IntArray::IntArray(int len)
{
m_pointer = new int[len];
for(int i=0; i<len; i++)
{
m_pointer[i] = 0;
}
m_length = len;
}
IntArray::IntArray(const IntArray& obj)
{
m_length = obj.m_length;
m_pointer = new int[obj.m_length];
for(int i=0; i<obj.m_length; i++)
{
m_pointer[i] = obj.m_pointer[i];
}
}
int IntArray::length()
{
return m_length;
}
bool IntArray::get(int index, int& value)
{
bool ret = (0 <= index) && (index < length());
if( ret )
{
value = m_pointer[index];
}
return ret;
}
bool IntArray::set(int index, int value)
{
bool ret = (0 <= index) && (index < length());
if( ret )
{
m_pointer[index] = value;
}
return ret;
}
void IntArray::free()
{
delete[]m_pointer;
}
main.cpp
int main()
{
IntArray a(5);
for(int i=0; i<a.length(); i++)
{
a.set(i, i + 1);
}
for(int i=0; i<a.length(); i++)
{
int value = 0;
if( a.get(i, value) )
{
printf("a[%d] = %d\n", i, value);
}
}
IntArray b = a;
for(int i=0; i<b.length(); i++)
{
int value = 0;
if( b.get(i, value) )
{
printf("b[%d] = %d\n", i, value);
}
}
a.free();
b.free();
return 0;
}