这是我的代码的简单示例
class base
{
protected:
int value;
public:
base();
base(const int);
base(const base &);
~base();
];
class derived:public base
{
protected:
derived * next; // a pointer to the same datatype.
public:
derived();
derived(const int);
derived(const base &);
derived(const derived &);// This is the problem.
~derived();
... ...
};
我的问题是如何编写派生类的复制构造函数,因为在派生类中有一个指向派生类的指针作为数据成员。我是否需要深拷贝才能复制此指针“derived * next”? “下一个 - >下一个”或“下一个 - >下一个>下一个”怎么样?它看起来像一个无限循环。
这是我到目前为止所写的内容
derived::derived(const derived & source):base(source)
{
if(next)
delete next;
next = new derived(source.next);
}
答案 0 :(得分:1)
我认为这里的两个误解是构造函数中传递的非相干参数以及递归链中没有停止条件。由于没有理由停止,它可能会进行无限循环。这样的事情应该这样做,假设结构不是圆形的:
derived::derived(const derived & source):base(source)
{
if(source.next) // if next is NULL, stop copying
{
// get the object that is pointed instead of pointer itself
next = new derived(*source.next);
}
}
更新:
正如建议的那样,检查构造函数中的next
成员是没用的。事实上,“防泄漏”安全性必须在分配级别完成,其中实际指针值可能会丢失。仍假设该结构是递归的良好候选者,通过这样做可以安全:
derived& derived::operator=(const derived & source)
{
if (this == &source) return *this; // copy of itself is already finish
freeMem(*this); // ensuring that the structure is empty prior to copy
if (source.next)
this->next = new derived(*source.next); // re-use the copy ctor
return *this;
}
考虑到freeMem
的可能性:
void derived::freeMem(const derived & source)
{
if (source.next)
{
freeMem(*source.next); // this will force to delete from the end
delete source.next;
source.next = NULL;
}
}
答案 1 :(得分:0)
如果next代表derived
的非循环链(又名列表),则代码可以是:
derived::derived(const derived & source) :base(source.value)
{
if (source.next) { // if the source has a next pointer
//delete next; // don't delete !
next = new derived(*source.next); // duplicate the object it contains
}
}
如果源具有有效的next
指针,则会复制链中的所有后续对象,直到链结束(使用null)。所有源对象都将保持不变(所有依赖对象的副本)。
只有在创建operator=
时才有意义,以避免指针被无意的=
覆盖。请记住,您必须避免将对象分配给自身。