第十九课:对象的构造(下)----------狄泰软件学院

一:两个特殊的构造函数

无参构造函数(没有参数的构造函数)
当类中没有定义构造函数时(注意这里是没有提供构造函数),编译器默认提供一个无参构造函数,并且其函数体为空,若类中定义了则不再提供
拷贝构造函数(参数为const class_name&)
当类中没有定义拷贝构造函数(注意这里是没有提供拷贝构造函数),编译器默认提供一个拷贝构造函数,简单进行成员变量成员变量成员变量值的复制

Class T//面试题,这个类看似什么也没有,其实有一个无参构造函数
{
};
#include <iostream>
using namespace std;

class Test
{
private:
    int i;
    int j;
public:
    int getI()
    {
        return i;
    }
    int getJ()
    {
        return j;
    }
    /*Test(const Test& t)//编译器提供的拷贝构造函数
    {
        i = t.i;
        j = t.j;
    }
    Test()
    {
    }*/
};


int main()
{
    Test t1;//编译器提供无参构造函数,如果手工提供了拷贝构造函数,就不会提供无参构造函数,这行就会报错
    Test t2 = t1;//编译器提供拷贝构造函数

    printf("t1.i = %d, t1.j = %d\n", t1.getI(), t1.getJ());//打印t1和t2的随机值都一样
    printf("t2.i = %d, t2.j = %d\n", t2.getI(), t2.getJ());
    system("pause");
    return 0;
}

二、拷贝构造函数的意义

兼容C语言的初始化方式
初始化行为能够符合预期的逻辑(t2 = t1)
浅拷贝:拷贝后对象的物理状态相同(编译器提供的拷贝构造函数是属于浅拷贝,单纯的成员值的复制)
深拷贝:拷贝后对象的逻辑状态相同

#

include <iostream>
using namespace std;

class Test
{
private:
    int i;
    int j;
    int* p;
public:
    int getI()
    {
        return i;
    }
    int getJ()
    {
        return j;
    }
    int* getP()
    {
        return p;
    }

    Test(int v)
    {
        i = 1;
        j = 2;
        p = new int;

        *p = v;
    }
    void free()
    {
        delete p;
    }
};


int main()
{
    Test t1(3);
    Test t2(t1);//使用默认的拷贝构造函数的话两个对象就会指向同一片申请的内存

    printf("t1.i = %d, t1.j = %d, *t1.p = %d\n", t1.getI(), t1.getJ(), *t1.getP());
    printf("t2.i = %d, t2.j = %d, *t2.p = %d\n", t2.getI(), t2.getJ(), *t2.getP());

    t1.free();//对同一片内存释放两次
    t2.free();
    system("pause");
    return 0;
}

为解决这种情况应该手工提供拷贝构造函数

Test(const Test& t)
    {
        i = t.i;
        j = t.j;
        p = new int;//重新new一块内存 
        *p = *t.p;
    }

这就是深拷贝
#

include <iostream>
using namespace std;
class Test
{
private:
    int i;
    int j;
    int* p;
public:
    int getI()
    {
        return i;
    }
    int getJ()
    {
        return j;
    }
    int* getP()
    {
        return p;
    }
    Test(const Test& t)
    {
        i = t.i;
        j = t.j;
        p = new int;

        *p = *t.p;
    }
    Test(int v)
    {
        i = 1;
        j = 2;
        p = new int;

        *p = v;
    }
    void free()
    {
        delete p;
    }
};

int main()
{
    Test t1(3);
    Test t2(t1);

    printf("t1.i = %d, t1.j = %d, *t1.p = %d\n", t1.getI(), t1.getJ(), *t1.getP());
    printf("t2.i = %d, t2.j = %d, *t2.p = %d\n", t2.getI(), t2.getJ(), *t2.getP());

    t1.free();
    t2.free();
    system("pause");
    return 0;
}

那么什么时候需要深拷贝?
对象中有成员指代了系统中的资源
成员指向了动态内存空间
成员打开了外存中的文件
成员使用了系统中的网络端口
一般原则:自定义拷贝构造函数,必然需要实现深拷贝

三、数组类的改进:提供一个拷贝构造函数

#include "IntArray.h"

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;
}

小结:

c++编译器会提供构造函数
无参构造函数用于定义对象的默认初始状态
拷贝构造函数在创建对象时拷贝对象的状态
对象的拷贝有深拷贝和浅拷贝两种
浅拷贝使得对象的物理状态相同
深拷贝使得对象的逻辑状态相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值