第17.18.19课.对象的构造

1.思考:对象中成员变量的初始值是多少?

上创建对象时,成员变量初始为随机值
上创建对象时,成员变量初始为随机值
静态存储区上创建对象时,成员变量初始为0值

#include <stdio.h>

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

Test gt;               //静态存储区

int main()
{
    printf("gt.i = %d\n", gt.getI());
    printf("gt.j = %d\n", gt.getJ());
    
    Test t1;            //栈区
    
    printf("t1.i = %d\n", t1.getI());
    printf("t1.j = %d\n", t1.getJ());
    
    Test* pt = new Test;        //堆区
    
    printf("pt->i = %d\n", pt->getI());        //这里恰好是0,只能说运气
    printf("pt->j = %d\n", pt->getJ());        //同上
    
    delete pt;
    
    return 0;

}

2.构造函数

c++中可以定义与类名相同的特殊成员函数。这种特殊的成员函数叫做构造函数。
a.构造函数没有任何返回类型的声明。
b.构造函数在对象定义时自动被调用。(定义会调用构造函数,赋值不会调用构造函数)

class Test
{
private:
    int i;
    int j;
public:
    int getI() 
    {
        return i;
    }
    
    int getJ()
    {
        return j;
    }
    
    Test()        //构造函数
    {
        i = 1;
        j = 2;
    }
};

3.带有参数的构造函数

a.一个类中可以存在多个重载的构造函数。
b.构造函数的重载遵循c++重载的规则。

class Test
{
public:
    Test()
    {
        printf("Test()\n");
    }
    
    Test(int v)
    {
        printf("Test(int v), v = %d\n", v);
    }
};

int main()
{
    Test t;         //调用 Test()
    Test t1(1);     //调用 Test(int v)
    Test t2 = 2;    //调用 Test(int v)

    t = t2;        //最后结果只显示了上面的三个。没有显示这个,是因为构造函数只有在定义的时候(初始化)才调用,其他时候不被调用。
}

注意:

对象定义和对象声明不同:
对象定义:申请对象的空间并调用构造函数(时间存在的)
对象声明:告诉编译器存在这样一个对象(虚无的)

4.手工调用构造函数

一般情况下构造函数在对象定义时被自动调用;特殊情况下,需要手工调用构造函数。

#include <stdio.h>

class Test
{
private:
    int m_value;
    
public:
    Test()
    {
        printf("Test()\n");
        
        m_value = 0;
    }
    
    Test(int v)
    {
        printf("Test(int v), v = %d\n", v);
    
        m_value = v;
    }
    
    int getValue()
    {
        return m_value;
    }
};

int main()
{
    Test ta[3] = {Test(), Test(1), Test(2)};        //手工调用构造函数
       
    for(int i=0; i<3; i++)
    {
        printf("ta[%d].getValue() = %d\n", i , ta[i].getValue());
    }
    
    Test t = Test(100);        //手工调用构造函数
    
    printf("t.getValue() = %d\n", t.getValue());
    
    return 0;
}

5.特殊的构造函数

一个类需要:构造函数和拷贝构造函数

a.无参构造函数

没有参数的构造函数
当类中没定义构造函数时,编译器默认提供一个无参的构造函数,并且其函数体为空

b.拷贝构造函数

参数为const class_name&的构造函数
当类中没有定义拷贝构造函数时,编译器提供一个拷贝构造函数,课进行简单的变量的值的赋值(默认即定义了拷贝构造函数后,编译器不会继续给类提供无参构造函数)

浅拷贝:拷贝后对象的物理状态相同。(单纯的,暴力的复制)(编译器默认提供的就是浅拷贝)
深拷贝:拷贝后对象的逻辑状态相同。(复制后能达到自己想要实现的逻辑,涉及到内存就需要使用深拷贝)

eg:
浅拷贝:

#include <stdio.h>

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

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());
    
    return 0;

}


当在类中加入内存释放时

void free()
{
    delete p;
}

出现错误。我们把一个地址中的内存释放了两次。

深拷贝:

#include <stdio.h>

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;
    }
    
    Test(const Test& t)
    {
        i = t.i;
        j = t.j;
        
        p = new int;
        
        *p = *t.p;
    }
    
    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();
    
    return 0;

}

6.什么时候需要进行深拷贝?

对象中有成员代指了系统中的资源时
a.成员指向了动态内存空间;
b.成员打开了外存中的文件;
c.成员使用了系统中的网络端口;

一般原则:
只要自定义拷贝构造函数,必然是深拷贝。不然就使用默认的。

posted @ 2019-11-08 15:54  人民广场的二道贩子  阅读(131)  评论(0编辑  收藏  举报