什么';复制构造函数有什么问题吗?为什么要使用可克隆接口? 编程C++时,我们在需要时创建复制构造函数(或者我们被教过)。几年前切换到Java时,我注意到现在正在使用可克隆接口。C#遵循定义iClonable接口的相同路线。在我看来,克隆是OOP定义的一部分。但我想知道,为什么要创建这些接口,而复制构造函数似乎已经被删除了
当我想到它时,我想到如果一个人需要复制一个类型未知的对象(比如有一个对基类型的引用),那么复制构造函数就没有用了。这似乎合乎逻辑。但我想知道是否还有其他原因我不知道,因为可克隆接口比复制构造函数更受青睐?这是最终类型的问题,以及通过复制构造函数没有解决的超类级联克隆操作的问题-它们是不可扩展的。但人们普遍认为Java克隆机制也严重受损;特别是子类不实现clone(),而是从实现cloneable的超类继承的问题 我强烈建议您仔细研究克隆,无论您选择哪种路径—您可能会选择clone()选项,但请确保您确切知道如何正确地进行克隆。它相当于等式()和HASCODE()看起来很简单,但是必须做得非常正确。< P>因为C++和java(和C语言)不是同一回事。C++没有内置的接口,因为接口不是语言的一部分。你可以用抽象类来伪造它们,但它们不是你对C++的看法。此外,C++中赋值通常是深的。 在Java和C中,赋值只涉及将句柄复制到内部对象。基本上当你看到:什么';复制构造函数有什么问题吗?为什么要使用可克隆接口? 编程C++时,我们在需要时创建复制构造函数(或者我们被教过)。几年前切换到Java时,我注意到现在正在使用可克隆接口。C#遵循定义iClonable接口的相同路线。在我看来,克隆是OOP定义的一部分。但我想知道,为什么要创建这些接口,而复制构造函数似乎已经被删除了,oop,class-design,Oop,Class Design,当我想到它时,我想到如果一个人需要复制一个类型未知的对象(比如有一个对基类型的引用),那么复制构造函数就没有用了。这似乎合乎逻辑。但我想知道是否还有其他原因我不知道,因为可克隆接口比复制构造函数更受青睐?这是最终类型的问题,以及通过复制构造函数没有解决的超类级联克隆操作的问题-它们是不可扩展的。但人们普遍认为Java克隆机制也严重受损;特别是子类不实现clone(),而是从实现cloneable的超类继承的问题 我强烈建议您仔细研究克隆,无论您选择哪种路径—您可能会选择clone()选项,但请确
SomeClass x = new SomeClass();
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()
是安全的)或不可变的(不需要复制),则需要复制构造函数。我想你的意思是“偶然”,而不是“偶然”。该死。我想我最终可以完成一个答案,而不需要那个丑陋的“编辑”标签。呵呵,谢谢你告诉我这件事