提问人:Descode 提问时间:3/29/2022 最后编辑:273KDescode 更新时间:3/29/2022 访问量:143
如何实现此程序的复制构造函数?[已结束]
How can I implement a copy constructor to this program? [closed]
问:
#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。
答:
-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;
评论
Point myPt2(5, 5);
myPt2 = Point(5,5);
x
y
int
Point(int x, int y) { this->x = x; this->y = y*>>>;<<< }
Point(int x, int y) { this->x = x; this->y = y; }
Point(int x, int y): x(x), y(y) { }
int getX(void) { return x; }
应该是int getX() const { return x; }