什么';复制构造函数有什么问题吗?为什么要使用可克隆接口? 编程C++时,我们在需要时创建复制构造函数(或者我们被教过)。几年前切换到Java时,我注意到现在正在使用可克隆接口。C#遵循定义iClonable接口的相同路线。在我看来,克隆是OOP定义的一部分。但我想知道,为什么要创建这些接口,而复制构造函数似乎已经被删除了

什么';复制构造函数有什么问题吗?为什么要使用可克隆接口? 编程C++时,我们在需要时创建复制构造函数(或者我们被教过)。几年前切换到Java时,我注意到现在正在使用可克隆接口。C#遵循定义iClonable接口的相同路线。在我看来,克隆是OOP定义的一部分。但我想知道,为什么要创建这些接口,而复制构造函数似乎已经被删除了,oop,class-design,Oop,Class Design,当我想到它时,我想到如果一个人需要复制一个类型未知的对象(比如有一个对基类型的引用),那么复制构造函数就没有用了。这似乎合乎逻辑。但我想知道是否还有其他原因我不知道,因为可克隆接口比复制构造函数更受青睐?这是最终类型的问题,以及通过复制构造函数没有解决的超类级联克隆操作的问题-它们是不可扩展的。但人们普遍认为Java克隆机制也严重受损;特别是子类不实现clone(),而是从实现cloneable的超类继承的问题 我强烈建议您仔细研究克隆,无论您选择哪种路径—您可能会选择clone()选项,但请确

当我想到它时,我想到如果一个人需要复制一个类型未知的对象(比如有一个对基类型的引用),那么复制构造函数就没有用了。这似乎合乎逻辑。但我想知道是否还有其他原因我不知道,因为可克隆接口比复制构造函数更受青睐?

这是最终类型的问题,以及通过复制构造函数没有解决的超类级联克隆操作的问题-它们是不可扩展的。但人们普遍认为Java克隆机制也严重受损;特别是子类不实现clone(),而是从实现cloneable的超类继承的问题

我强烈建议您仔细研究克隆,无论您选择哪种路径—您可能会选择clone()选项,但请确保您确切知道如何正确地进行克隆。它相当于等式()和HASCODE()看起来很简单,但是必须做得非常正确。

< P>因为C++和java(和C语言)不是同一回事。C++没有内置的接口,因为接口不是语言的一部分。你可以用抽象类来伪造它们,但它们不是你对C++的看法。此外,C++中赋值通常是深的。 在Java和C中,赋值只涉及将句柄复制到内部对象。基本上当你看到:

SomeClass x = new SomeClass();
或C++中,C++中没有一个间接的构建层。在C++中,你写:

SomeClass* x = new SomeClass();
<> > C++中赋值包含的引用值:

*x = *another_x;

在Java中,您可以访问“real”对象,因为没有像*x这样的解引用操作符。因此,要进行深度复制,需要一个函数:clone()。Java和C都将该函数包装到一个接口中。

我认为这是因为Java和C中对引用类型的复制构造函数没有这样的内在需求。在C++对象中命名。例如,当从函数返回指针时,您可以(而且您通常会)复制(并且在C++1x中移动)它们,因为返回指针需要您分配动态内存,这将是一个缓慢而痛苦的管理过程。语法是T(x),因此使构造函数接受T引用是有意义的。C++无法生成克隆函数,因为这将需要再次按值返回对象(因此也需要另一个副本)。


但在Java中,对象是未命名的。只有对它们的引用可以复制,但对象本身不会被复制。对于实际需要复制它们的情况,可以使用clone调用(但我在其他anwers中读到clone有缺陷。我不是java程序员,因此无法对此作出评论)。因为返回的不是对象本身,而是对它的引用,所以克隆函数就足够了。还可以覆盖克隆函数。这对复制构造函数不起作用。顺便说一下,在C++中,当你需要复制一个多态对象时,也需要一个<代码>克隆< /Cord>函数。它有一个名字,所谓的虚拟副本构造函数

我想你的观点不对。我给你两分钱

从根本上说,存在一个问题:在不知道确切的类类型的情况下创建类的克隆。如果使用复制构造函数,则不能

以下是一个例子:

class A {
public A(A c) { aMember = c.aMember }
    int aMember;
}

class B : A {
public B(B c) : base(c) { bMember = c.bMember }
    int bMember;
}

class GenericContainer {
public GenericContainer(GenericContainer c) {
    // XXX Wrong code: if aBaseClass is an instance of B, the cloned member won't 
    // be a B instance!
    aBaseClass = new A(c.aBaseClass);
}
    A aBaseClass;
}
Clone方法(如果声明为virtual)可以创建泛型成员的正确类实例

这个问题对于每种语言都是常见的,C+C++或java……/p>
也许这就是你的意思,但我无法从任何答案中理解这一点。

我认为这只是因为一旦定义了复制构造函数,就再也无法传递引用本身了。(除非它有一个这样做的函数……但这并不比使用clone()方法简单。)
在C++中,它不是问题:你可以传递整个对象或它的引用。

< p>只是想添加在java中,复制构造函数不是完全没有用的。 在某些情况下,您的类有一个可变非最终类型的私有实例变量,例如
Date
,并且该变量有一个setter和getter。在setter中,您应该创建给定日期的副本,因为调用方可以稍后修改它,从而操纵对象的内部状态(通常是偶然的,但可能是有意的)。在吸气剂中,也需要同样的预防措施

防御复制可以通过调用
clone()
(类
Date
是可克隆的),但是恶意调用方可以使用
Date
子类调用setter,该子类用
{return this;}
覆盖
clone()
方法,因此调用方可能仍然能够操作您的对象。这就是复制构造函数发挥作用的地方:通过调用
newdate(theDate)
,您一定会得到一个新的
Date
实例,该实例的时间戳与给定日期相同,两个日期实例之间没有任何连接。在getter中,您可以使用clone方法,因为您知道私有变量将属于类
Date
,但是为了一致性,通常也使用copy构造函数


还要注意,如果
Date
类是final(调用
clone()
是安全的)或不可变的(不需要复制),则需要复制构造函数。

我想你的意思是“偶然”,而不是“偶然”。该死。我想我最终可以完成一个答案,而不需要那个丑陋的“编辑”标签。呵呵,谢谢你告诉我这件事