《实用C++》第36课 对象的赋值与复制及拷贝构造函数

本文转载自:VC驿站

https://www.cctry.com/thread-289974-1-1.html

1、对象的赋值:
何为对象的赋值?我们先来说说赋值,赋值咱们之前也给大家讲解过。说到赋值咱们肯定能想到=等号,一般赋值指的都是用=等号赋值,例如:

int a = 5; //赋值操作
int b = a; //这也是赋值

那么对象也是一样的,也是用=等号,不过赋值的目标不是int类型的整型数了,而是用一个对象给同类的另外一个对象赋值。这个过程是通过成员复制来完成的,即,将一个对象的成员的值一个一个的复制给另外一个对象的对应成员。

2、对象的赋值举例:
有一个矩形的类,CMyRect 的声明如下:

class CMyRect
{
public:
    CMyRect(int w = 0, int h = 0):width(w), height(h){};
public:
    int width; //矩形的宽
    int height; //矩形的高
};

接下来,我用这个矩形类定义两个对象:

CMyRect rect_a(200, 100), rect_b;

之后,我用 rect_a 给 rect_b 赋值,如下:

rect_b = rect_a;

之后,我们看看 rect_b 的宽和高都是多少呢?咱们来调试一下,看看具体的值。调试过程见视频教程的详细讲解!

3、对象赋值的注意事项:
①、对象的赋值,只是对对象的成员变量的赋值,对于成员函数来说不理会,也不做赋值处理,因为本身每个类的成员函数就一份而已所以也不需要赋值。这个之前给大家讲解this指针的时候提过,如果大家忘记了,可以看看以前的课程说明文档,在这里:《实用C++》第32课 this指针:https://www.cctry.com/thread-289911-1-1.html
②、类似上面的矩形类 CMyRect 的对象是可以直接用=等号赋值的,但是有一些成员是没办法用=等号赋值的,例如,成员变量是其他一种类对象,那么此时的解决办法就是重载类的=等号运算符,这个以后会给大家讲解;
③、还有一种情况下,使用对象的赋值也是非常危险的,例如咱们上节课最后给大家使用的那个 CStudent 类型,咱们来试试:
对象的赋值代码如下:

void test()
{
    CStudent stud_1("zhangsan", 'f', 1001, 20);
    CStudent stud_2;
    stud_2 = stud_1;
}

int main(int argc, char* argv[])
{
    test();
    return 0;
}

执行之后,程序崩溃了,如下图:
《实用C++》第36课 对象的赋值与复制及拷贝构造函数 
大家想想为什么呢?为什么会崩溃,原因见视频教程讲解!

4、对象的复制:
刚才给大家说了对象的赋值,是利用=等号运算符将一个对象的成员变量赋值给另外一个同类对象的成员变量。可以说是对已经存在的两个对象进行操作。那么对象的复制呢?对象的复制是一个对象从无到有的一个过程,在对象创建的时候就以一个已经存在的对象为源头进行创建本对象。

例如:

Student zhangsan = {"zhangsan", 1002, 20};
Student lisi(zhangsan);
Student wangwu = lisi;

对于对象 lisi 和 wangwu 来说都是在创建的时候以 zhangsan 这个对象为源对象进行创建的,所以这里面就是用到了对象的复制操作。
这里面咱们来调试下上面的代码,看看具体的信息是否复制过去了。详细调试过程见视频教程!

5、复制/拷贝构造函数:
上面的代码中这句话:Student lisi(zhangsan); 大家看着是不是有点眼熟,我们在给大家讲解构造函数的时候就用到过类似的写法,具体在:
《实用C++》第33课 类的构造函数:https://www.cctry.com/thread-289921-1-1.html
我们过去看一眼!

所以,按理说 Student lisi(zhangsan); 这句代码也应该调用的是构造函数,对不对?没错,确实是,只不过这个构造函数有点特殊,名为拷贝构造函数。
原型如下:

class Student
{
public:
    char name[50];
    int num;
    int age;
    Student(char* pname, int t_num, int t_age) :num(t_num), age(t_age)
    {
        strcpy(name, pname);
    }

    Student(Student& stud)
    {
        strcpy(name, stud.name);
        num = stud.num;
        age = stud.age;
    }
};


6、拷贝构造函数的特点:
①、也是构造函数,所以函数名字就是类名字,并且无返回值;
②、参数上有点特殊,参数是一般是本类的对象的引用;
③、如果类没有提供拷贝构造函数,那么编译器会默认生成一个拷贝构造函数,作用比较单一,只是简单的将成员变量的值进行复制过去而已。

7、拷贝构造函数实现的必要性:
刚才已经跟大家说了,如果一个类没有提供拷贝构造函数,那么那么编译器会默认生成一个。既然编译器都可以默认生成了,我们为什么还要实现呢?
①、类的成员变量中有一些无法进行赋值的,此时就需要自定义实现拷贝构造函数;
②、针对类似上节课给大家讲解的 CStudent 类的实现方式上,调用起来也非常危险,咱们再来实验一下:

void test()
{
    CStudent stud_1("zhangsan", 'f', 1001, 20);
    CStudent stud_4(stud_1);
}

之后,我们来执行下代码,执行完 test 函数之后,程序又崩溃了。为什么呢?具体原因及解决方法见视频教程讲解!

8、小作业:
实现 CStudent 类的拷贝构造函数,让 第 7 点的代码不崩溃!要慎重 new 和 delete 哦!

第36课视频教程下载地址:

https://www.cctry.com/thread-289974-1-1.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值