zoukankan      html  css  js  c++  java
  • [Effective C++ --012]复制对象时勿忘其每一个成分

    引言:

       在深拷贝和浅拷贝的理解中,我们知道了“拷贝构造函数”一词,并且也了解了它的构成。

    A(const A& r);  // 形式有多种,在这里只列出一个

    因此,在值传递的应用场景里,我们可以写出以下的拷贝构造函数:

     1 #include <iostream>
     2 #include<string>
     3 using namespace std;
     4 
     5 class A {
     6 public:
     7     A(int i) : count(i) {};
     8     A(const A& r) {                   // 拷贝构造函数
     9         count = r.count;
    10     }
    11     ~A() {};
    12     void out() {
    13         cout << "count:" << count << endl;
    14     }
    15 private:
    16     int count;
    17 };
    18 
    19 int main()
    20 {
    21     A a(1);
    22     A a1(a);              // 将a的临时变量传递进去
    23     
    24     a1.out();
    25     return 0;
    26 }

    输出结果:1

    一、不要忘记复制每一个成员

        在引言的例子里,我们完整将count通过拷贝构造函数复制了过来。如果我们此时有了新需求,需要给类A增加一个成员x,那么在拷贝构造函数中,一定不要忘记拷贝x!

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class A {
     5 public:
     6     A(int i, int j) : count(i),x(j) {};
     7     A(const A& r) {
     8         count = r.count;
     9         x = r.x;                                          // 不要忘记赋值成员x!
    10     }
    11     ~A() {};
    12     void out() {
    13         cout << "count:" << count << endl;
    14         cout << "x:" << x << endl;
    15     }
    16 private:
    17     int count;
    18     int x;
    19 };
    20 
    21 int main()
    22 {
    23     A a(1, 1);
    24     A a1(a);
    25     
    26     a1.out();
    27     return 0;
    28 }

    值得注意的是:如果我们遗漏了第9行代码,编译器是不会报错的,甚至也能正常运行,但是不会得出想要的结果1!

     二、拥有"显示"拷贝构造函数发生继承

    在上面的A类中, 我们已经针对A写出了显示的拷贝构造函数。但是如果此时发生了继承会怎么样呢?

    假设我们有class  B: public A

     1 class B: public A {
     2 public:
     3     B(int x, int y) : b1(x),b2(y){};
     4     B(const B& r){
     5         b1 = r.b1;
     6         b2 = r.b2;
     7     };
     8     ~B() {};
     9     void out() {
    10         cout << "b1:" << b1 << endl;
    11         cout << "b2:" << b2 << endl;
    12     }
    13 private:
    14     int b1, b2;
    15 };

    简直跟class A一样有木有?

    于是我们开始编译 B b(2,2); B b1(b);

    会出现以下错误:

    error C2512: 'CPS' : no appropriate default constructor available

    这是为什么呢?

    在类B的拷贝函数中看起来好像赋值了B中的每一个东西,但是它们复制的只是B声明的成员变量b1,b2;B继承A的成员变量附件完全木有得到复制啊!

    在创建对象时,会首先调用A类的构造函数。而在B的初始化列表中,并没有显示的对基类的构造函数进行调用。那么,系统会默认调用A的无参构造函数,但是你的A类并没有定义无参构造函数,所以出错了!

    改法如下:

     1 class B: public A {
     2 public:
     3     B(int x, int y) : b1(x),b2(y), A(x, y) {};    // 调用A的构造函数
     4     B(const B& r) : A(r.b1, r.b2){                // 调用A的构造函数
     5         b1 = r.b1;
     6         b2 = r.b2;
     7     };
     8     ~B() {};
     9     void out() {
    10         cout << "b1:" << b1 << endl;
    11         cout << "b2:" << b2 << endl;
    12     }
    13 private:
    14     int b1, b2;
    15 };

    ◆总结

    1.拷贝函数应该确保复制对象内的所有成员变量及所有的基类成分。

    2.不要尝试以某个拷贝函数实现另一个拷贝函数。应该将共同机能放进第三个函数中,并由两个拷贝函数共同调用。

  • 相关阅读:
    poj 2187 Beauty Contest(旋转卡壳)
    poj 2540 Hotter Colder(极角计算半平面交)
    poj 1279 Art Gallery(利用极角计算半平面交)
    poj 3384 Feng Shui(半平面交的联机算法)
    poj 1151 Atlantis(矩形面积并)
    zoj 1659 Mobile Phone Coverage(矩形面积并)
    uva 10213 How Many Pieces of Land (欧拉公式计算多面体)
    uva 190 Circle Through Three Points(三点求外心)
    zoj 1280 Intersecting Lines(两直线交点)
    poj 1041 John's trip(欧拉回路)
  • 原文地址:https://www.cnblogs.com/hustcser/p/4092911.html
Copyright © 2011-2022 走看看