C++构造函数、复制函数易错点

C++中复制函数在三种情况下自动调用:

  1. 用一个对象初始化另一个对象
  2. 函数的参数为对象
  3. 函数的返回值为对象

下面用几个代码片段解释复制函数的调用中的一些常见“坑”:

一:默认复制函数的自动调用

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class Point
 5 {
 6 public:
 7     Point(int X, int Y) :x(X), y(Y) {};
 8     void showCoordinate()
 9     {
10         //展示坐标
11         cout << "X=" << x << "\tY=" << y << endl;
12     }
13 private:
14     int x;
15     int y;
16 };
17 
18 int main()
19 {
20     Point p1(0, 0);
21     p1.showCoordinate();
22     Point p2 = p1;          //此事并未编写显示的复制函数,系统会自动生成Point的一个自适应复制函数
23     p2.showCoordinate();    //发现 p2 的坐标与 p1 相同
24     cout << &p1 << endl; 
25     cout << &p2 << endl;    //显然,p2 只是 p1 复制函数之后的新的对象,在内存中的地址并不相同
26     return 0;
27 }

二:不存在合适的构造函数【实质上还是复制函数的问题】

#include<iostream>
using namespace std;

class Point
{
public:
    Point(int X, int Y) :x(X), y(Y) {};
    Point(Point& p);
    int getX() { return x; }
    int getY() { return y; }
private:
    int x;
    int y;
};
Point::Point(Point& p) {
    x = p.x;
    y = p.y;
}
class Line
{
public:
    Line(Point temp_p1, Point temp_p2) {
        p1 = temp_p1;
        p2 = temp_p2;
    };
private:
    Point p1;
    Point p2;
};

int main()
{
    Point p1(0, 0);
    Point p2 = p1;        //此时复制函数仍然可以正常调用,但是 24 行报错
    /**
    * C2512“Point” : 没有合适的默认构造函数可用    
    * E0291    类 "Point" 不存在默认构造函数
    */

    return 0;
}

为什么出现这种情况,实质上是因为1:Line的构造函数中使用了无参数的构造函数,但是只有当没有编写构造函数时,系统会自动生成一个没有参数的构造函数,而编写了构造函数之后系统并不会自动生成。

一个治标不治本的方法是,在class Point中加入一个无参数的构造函数。但是问题显而易见,么有参数的构造函数并么有实际意义。所以只能通过类的组合,将Point类内嵌在Line类中。

将其改为:

Line(Point temp_p1, temp_p2) :p1(temp_p1), p2(temp_p2);

 至此,可以编写计算线段长度的程序:

 1 #include<iostream>
 2 #include<cmath>
 3 using namespace std;
 4 
 5 class Point
 6 {
 7 public:
 8     Point(int X, int Y) :x(X), y(Y) {};
 9     Point(Point& p);
10     int getX() { return x; }
11     int getY() { return y; }
12 private:
13     int x;
14     int y;
15 };
16 Point::Point(Point& p) {
17     x = p.x;
18     y = p.y;
19 }
20 class Line
21 {
22 public:
23     Line(Point temp_p1, Point temp_p2) : p1(temp_p1), p2(temp_p2) {};
24     double getLen();
25 private:
26     Point p1;
27     Point p2;
28 };
29 
30 //计算线段长度,比较简单,可以设置为内联
31 inline double Line::getLen()
32 {
33     int a = abs(p1.getX() - p2.getX());
34     int b = abs(p1.getY() - p2.getY());
35     double len = sqrt(a * a + b * b);
36     return len;
37 }
38 
39 int main()
40 {
41     Point p1(0, 0);
42     Point p2(3, 4);
43     Line line1(p1, p2);
44     cout << line1.getLen() << endl;    //输出线段长度
45 
46 
47     return 0;
48 }

 

版权声明:本文为Rebel3原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Rebel3/p/14390706.html