C++初学解惑(5)——构造函数(中)

C++初学解惑(5)——构造函数(中)

 

三、复制构造函数

 

    1.存在的理由

 

    厨师做烹饪的时候总要往锅里加入各式各样的调料,调料的种类、数量在相当大的程度上就决定了菜肴的口感;经验丰富的厨师总是擅长于根据顾客的品味差异来调节调料的投入,以迎合顾客的喜好。我们在炮制对象的时候亦如此:通过重载不同具有参数表的构造函数,可以按我们的需要对新创建的对象进行初始化。譬如,对于复数类Complex,我们可以在创建时指定实部、虚部,它通过“投入”的两个double参数来实现;而对于整型数组类IntArray,我们亦可以在构造函数中“投入”一个int值作为数组对象的初始大小,如果需要,我们还可以再“撒进”一个内部数组作为数组各元素的初始值,等等。嗯,总之,就是说我们可以通过向类的构造函数中传入各种参数,从而在对象创建之初便根据需要可对它进行初步的“调制”。假使我们已经做好了一道菜,呃,不,是已经有了一个对象,比如说,一个复数类Complex的对象c,现在我们想新创建一个复数对象d,使之与c完全相等,应该怎么办?噢,有了上节的经验,我知道你会兴冲冲地走到电脑,敲出类似于下面的代码:

 

    Complex d(c.getRe(), c.getIm());     // getRe()与getIm()分别返回复数的实、虚部

 

    很好,它可以正确的工作,不是吗?不过,再回过头两欣赏几眼之后,你是否和我一样开始觉得似乎这样有些冗长?而且,应该看到复数类是一个比较简单的抽象数据类型,它提供的公有接口可以让我们访问到它所有的私有成员变量,所以我们才得以获得c的所有的“隐私”数据来对d进行初始化;但有相当多的类,是不能也不该访问到它所有的私有对象的,退一步说,就算可以完全访问,我们的构造函数参数表也未必总能精细地、一丝不苟地刻画对象,例如对于IntArray类的某个对象,例如a,可能它会包含一千个元素,但我们不可能写

 

    IntArray copy_of_a(a.size(), a[0], a[1], a[2], ..., a[999]);  // 足够详细的刻画,同时也足够愚蠢

 

    唔,看来我们错就错在试图用数量有限的辅助参数来刻画我们的对象,而它往往是不合适的。要想以对象a来100%地确定对象b,就必须让对象b掌握对象a的100%的信息,也就是说,构造函数中所传入的参数应该包含对象a的100%的信息。谁包含了“对象a的100%的信息”呢?看上去似乎是一道难题,哦,我们似乎被前面各个杂乱的参数表弄得头晕脑胀,但我们不应该忘却从简单的方面考虑问题的法则,包含“对象a的100%的信息”的家伙,不应该是一群数量巨大的变量,不应该是一组令人恐惧的参数,它应该就是...就是对象a本身。

    啊哈,真是废话。别管这么多,我们现在要让复数d初始化之后立刻等于复数c,就可以写

 

    Complex d(c);    // 嗯...完美的表示

 

    “等等...”你也许会提醒说,“你好像还没有定义与之对应的构造函数。”

    这是一个非常好心的提醒,不过我可以带着愉悦的心情告诉你:C++对于“以与自己同类型的对象为作为唯一参数传入的构造函数”已经做了默认的定义,对于这个默认的构造函数所创建的对象,将与作为参数传入的对象具有完全相同的内容:实际上,这个过程一般是以“位拷贝”的方式进行的,即是将参数对象所占的那一块内存的内容“一股脑”地拷贝到新创建的对象所处的内存区块中,这样做的结果,便使得新创建的对象与参数对象内有完全相同的成员变量值,无论是公有的还是私有的,因而,我们也就得以以一个已存在的对象来初始化一个新的对象,当然,两者应该是同一类型的。

    你也许会对“为何C++要默认提供这样一个构造函数”感兴趣。实质上,不仅仅是上面的“声明对象并初始化”的例子要使用到这个特性,在一些更普遍的情况、同时也是我们所不注意的情况中,必须要使用到这个功能,例如:进行值传递的函数调用。考虑下面的代码片断:

 

    void swap(int a, int b)

    {

        int temp = a;

        a = b;

        b = temp;

    }

 

    int main()

    {

       int x = 1, y = 2;

       swap(x, y);

阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C++ 默认构造函数是在没有显式定义构造函数的情况下自动生成的特殊成员函数。它通常用于在创建对象时进行初始化操作。默认构造函数无参数,不接受任何实参。当我们通过调用类的构造函数来创建对象时,如果没有提供实参,则编译器会自动调用默认构造函数。 默认构造函数的作用是确保对象的所有成员变量都被正确初始化。例如,如果一个类有一个int类型的成员变量,那么在默认构造函数,可以将该成员变量初始化为0。如果没有默认构造函数,当我们创建对象时,该成员变量可能会未被初始化,导致程序运行时出现意外结果。 另一个重要的地方是,当我们定义了类的其他构造函数时(比如有参数的构造函数),默认构造函数依然会被生成。这是因为在某些情况下,我们可能只想使用默认构造函数来创建对象,而不希望传递实参。此时,默认构造函数就能满足需求。当我们重载构造函数时,可以使用默认参数来实现默认构造函数的功能。 需要注意的是,默认构造函数在一些特殊情况下可能不会被生成。例如,如果我们显式定义了有参数的构造函数,但没有提供默认构造函数,那么编译器将不会自动生成默认构造函数,这意味着我们不能再使用无参的方式来创建对象。 总之,理解C++默认构造函数的作用和用法对于编写高质量的代码至关重要。它可以帮助我们确保对象的正确初始化,并且在一些特殊情况下可以提供方便的使用方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kusk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值