/** @file ListP.cpp
* ADT list - Pointer-based implementation. */
#include <iostream>
#include <cstddef> // for NULL
#include <new> // for bad_alloc
#include "ListP.h" // header file
using namespace std;
List::List() : size(0), head(NULL)
{
} // end default constructor
List::List(const List& aList) : size(aList.size)
{
if (aList.head == NULL)
head = NULL; // original list is empty
else
{ // copy first node
head = new ListNode;
head->item = aList.head->item;
// copy rest of list
ListNode *newPtr = head; // new pointer
// newPtr points to last node in new list
// origPtr points to nodes in original list
for (ListNode *origPtr = aList.head->next; origPtr != NULL; origPtr = origPtr->next)
{
newPtr->next = new ListNode;
newPtr = newPtr->next;
newPtr->item = origPtr->item;
} // end for
newPtr->next = NULL;
} // end if
} // end copy constructor
void List::copy(const List& aList)
{
List::List(aList);
} // end copy
我正在尝试创建一个名为copy的方法,它只调用复制构造函数。当我在main中测试此方法时,目标列表仍然为空。我已经逐步完成它并执行了所有正确的行,但是当复制构造函数返回时似乎没有保存。我觉得这与范围有关,但无法查明问题。这是驱动程序:
#include <iostream>
using namespace std;
#include "ListP.h"
int main ()
{
List aList;
ListItemType dataItem;
aList.insert(1, 9);
aList.insert(2, 4);
aList.insert(3, 1);
aList.insert(4, 2);
List bList;
bList.copy(aList);
bList.retrieve(1, dataItem);
cout << dataItem << endl;
cout << bList.getLength() << endl;
return 0;
}
答案 0 :(得分:4)
如果我理解你的问题,你就无法做你想做的事。
在对象上调用任何其他方法之前,必须完全构造对象(这里有一个例外,我会回过头来看)。此外,一个对象只能构造一次(*)。因此,当您可以调用复制方法时,该对象已经构建,您不能(也不应该)第二次构造它。
无法在未完全构造的对象上调用方法的一个例外(即构造函数尚未返回)是构造函数本身可以在部分构造的对象上调用方法。因此,您可以从复制构造函数中调用复制方法,但反之亦然。
也就是说,如果你的对象提供了一个优化的交换函数,那么可能会考虑一个标准技巧:
void List::copy(const List& aList)
{
List acopy(aList);
swap(*this, acopy);
}
这会生成aList的副本,然后使用此副本交换对象的当前内容。现在具有列表内容的副本将在复制返回时被正确销毁。
最后,如果您打算这样做,目前的建议实际上是调整一下并以这种方式写下来:
void List::copy(List aList)
{
swap(*this, aList);
}
在某些情况下,这可能更有效(并且效率从不低)。
* - 您可以做奇怪的事情并使用placement new构建一个对象两次。但没有充分的理由这样做以及为什么不这样做的原因很多。
答案 1 :(得分:2)
在您的驱动程序中,您有
List bList;
bList.copy(aList);
相反,使用
调用复制构造函数List bList(aList);
或
List bList = aList;
...查看“复制”方法:构造函数创建一个新实例。 List :: copy方法调用复制构造函数,在堆栈上创建List的新实例。然后它返回,你的新实例就消失了。
您可能想要的而不是“复制”方法是定义赋值运算符
List& List::operator=(const List& aList)
{
if (this != &aList)
{
// Do your copying here
}
return *this;
}
然后你的司机可以说
List bList;
// ...Presumably manipulate bList in some other ways in-between...
bList = aList;
要从同一个类的另一个方法内部调用赋值运算符,比如说
*this = aList;
或
operator=(aList);
我发现后者很尴尬。但是,如果要获取指向成员函数的指针,则可能需要明确地按名称引用运算符。
答案 2 :(得分:1)
问题是,如果这样的语法如此简单,那么为什么要使用copy
方法:&gt; (除非你是那些希望明确说明副本的防守人员之一 - 然后我提交,我也是其中之一)。
您可能也有兴趣复制(分配)运算符:
List& List::operator=(const List& aList)
{
//
}
至于无法调用复制构造函数,请参阅C++ FAQ Lite on Constructors。这个thread也提出了同样的问题。
无法从类中显式调用构造函数是C ++标准文档的一部分,但是maaan,你不想读那个东西......但是; - )
答案 3 :(得分:1)
构造函数很特殊,因为当对象未初始化时,它们仅被称为 。因此,您不能将任何简单函数,副本或其他方式调用。 C ++需要这样做,因为它有助于编写代码,当您添加功能时,代码会减少。
您可能希望将复制构造函数的主体移至Copy()
并从Copy()
调用List::List(List const&)
。