如何实现此程序的复制构造函数?[已结束]

How can I implement a copy constructor to this program? [closed]

提问人:Descode 提问时间:3/29/2022 最后编辑:273KDescode 更新时间:3/29/2022 访问量:143

问:


编辑问题以包括所需的行为、特定问题或错误以及重现问题所需的最短代码。这将有助于其他人回答这个问题。

去年关闭。

#include <iostream>

using namespace std;

class Point{
private: 
  int x, y;
public:
  Point(int x, int y) { this->x = x; this->y = y } 
  Point(const Point &p) { x = p.x; y = p.y; }

  int getX(void) { return x; }
  int getY(void) { return y; }
};

int main(){
    Point myPt(1,2);
    Point myPt2 = myPt;

    cout << myPt.getX() << " " << myPt.getY() << endl;
    cout << myPt2.getX() << " " << myPt2.getY() << endl;
    
  return 0;
}

我想将 myPt2 设置为不同的值,同时保持 myPt 值相同,即使在将 myPt2 设置为 myPt 之后也是如此(执行此操作时出现重新定义错误)。例如,Point myPt(1,2);点 myPt2 = myPt;....print output,然后设置 myPt2(5, 5) 并再次打印语句:我想要输出 1 2 \n5 5。

C++ OOP 初始化 复制构造函数

评论

1赞 paddy 3/29/2022
您已经实现了一个复制构造函数。您提到的“重新定义错误”可能是因为您正在尝试定义具有相同名称的标识符。你应该展示这段代码,然后我们可以进行真正的讨论。但是因为你没有,我假设你写了一个重新定义,而你想要Point myPt2(5, 5);myPt2 = Point(5,5);
0赞 user4581301 3/29/2022
绝大多数情况下,当类拥有的所有资源都是自我管理时,您不需要复制构造函数。在本例中,类的唯一资源是 和 ,并且 s 负责自己的复制。有关详细信息,请参阅三法则(和朋友)。xyint
0赞 user4581301 3/29/2022
我在上面的代码中看到的唯一错误是缺少分号:Point(int x, int y) { this->x = x; this->y = y*>>>;<<< }
0赞 user4581301 3/29/2022
旁注:仔细阅读成员初始值设定项列表。这里不是那么重要,变成了,但它以后会为你省去很多麻烦。Point(int x, int y) { this->x = x; this->y = y; }Point(int x, int y): x(x), y(y) { }
1赞 Eljay 3/29/2022
int getX(void) { return x; }应该是int getX() const { return x; }

答:

-1赞 Ranoiaetep 3/29/2022 #1
如果我理解正确的话,您正在寻找一种使以下代码工作的方法:
int main(){
    Point myPt(1,2);
    Point myPt2 = myPt;
    myPt2(5, 5);

    cout << myPt.getX() << " " << myPt.getY() << endl;    // prints "1 2"
    cout << myPt2.getX() << " " << myPt2.getY() << endl;  // prints "5 5"
}

若要允许该语法,必须重载调用运算符 ,以接受 2 个整数:myPt2(5, 5)operator()

class Point {
  ⋮
public:
  void operator()(int x, int y)
  {
      this->x = x; this->y = y;
  }
  ⋮
};


但是,我强烈建议不要采用这种方法。相反,当您想要将值重新分配给 时,您实际上应该使用以下语法调用复制赋值运算符:myPt2

myPt2 = Point(5, 5);

要编写自己的复制分配运算符,如下所示:

class Point {
  ⋮
public:
  Point& operator=(const Point &p)
  {
      x = p.x;
      y = p.y;
      return *this;
  }
  ⋮
};

事实上,根据你的类所做的事情,你真的不需要编写复制构造函数或复制赋值运算符。这就是您所需要的:

class Point{
private: 
  int x, y;
public:
  Point(int x, int y) { this->x = x; this->y = y; } 

  int getX(void) { return x; }
  int getY(void) { return y; }
};

任何类型的复制结构都将自动完成。实际上,只有在具有不可复制的成员,或者正在寻找某些自定义复制行为(例如执行深度复制指针)时,才需要定义自己的复制构造函数。

评论

0赞 Descode 3/29/2022
好的,谢谢。那么,如果你为这个程序编写了一个复制构造函数,你会怎么做呢?此外,我在我的 Gaddis 书中看到您必须动态分配内存并使用指针变量。你能用简单的英语向我解释一下吗?我已经完成了我的研究,我只是不明白使用复制构造函数的明确方法,youtube 和书籍上的所有内容看起来都不同。有什么方法可以每次都有效?我是一名大学生,还在学习。希望这个问题值得你花时间。多谢!
0赞 user4581301 3/29/2022
@Descode 您的复制构造函数是正确的,但不是必需的。如果您将其省略或显式地排除在外,编译器将为您生成它。Point(const Point &p) = default;default
1赞 paddy 3/29/2022
操作员过载是一种可怕的反模式。我不支持这个建议。
1赞 user4581301 3/29/2022
当类包含管理自己的复制的简单成员或复杂成员(具有正确的复制构造函数和赋值运算符)时,无需执行任何操作。带有指针的示例,所指向的对象需要特殊处理。复制指针的默认行为是,最终会得到两个包含相同地址的指针,这两个指针都指向同一个对象。如果 instance 到达其析构函数,则 会删除两个实例的 ,留下仍然存活的实例作为定时炸弹,在不久的将来会爆炸。delete p;p
1赞 paddy 3/29/2022
我的观点是,定义一个类似函数的运算符重载来修改值是对运算符语义的滥用。它依靠语法糖来提供对构造函数的一些熟悉,而不是自我记录的明确指定的调用(例如:)。仅仅因为你可以做到并不意味着你应该这样做。当你以“这是怎么做”打开你的答案,然后是最糟糕的解决方案之一时,它引发了我的反应和评论。使用晦涩的重载而不是描述性函数是一种反模式。Set(int, int)
-1赞 Chris Dodd 3/29/2022 #2

您的程序已经有一个复制构造器-- --用于从另一个 Point 对象构造一个新的 Point 对象。Point(const Point &p)

若要更改现有 Point 对象,需要复制赋值运算符。您可以在 Point 类中将其定义为:

Point &operator=(const Point &p) { x = p.x; y = p.y; return *this; }

甚至只是

Point &operator=(const Point &) = default;