você pode chamar um construtor de cópia de outro método?
-
19-09-2019 - |
Pergunta
/** @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
Eu estou tentando criar um método chamado copiar que simplesmente chama o construtor de cópia. Quando eu testar este método em main na lista de destino ainda permanece vazio. Tenho passou por ela e todas as linhas direitas são executadas, mas quando o construtor de cópia retorna nada parece ser salvo. Eu sinto isso tem algo a ver com escopo, mas não pode identificar o problema. Aqui está o programa do controlador:
#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;
}
Solução
Se entendi sua pergunta, você não pode fazer o que você está tentando fazer.
Antes de chamar quaisquer outros métodos em um objeto, o objeto deve ser totalmente construído (há uma exceção aqui, eu vou voltar a isso). Além disso, um objecto apenas pode ser construída uma vez (*). Portanto, no momento em que você poderia chamar o seu método de cópia, o objeto já estaria construído e você não pode (e não deve) construí-la uma segunda vez.
A única excepção a não ser capaz de chamar um método de um objecto que não está totalmente construído (isto é, o construtor ainda não retornou) é que um construtor si pode chamar um método no objecto parcialmente construída. Então, você poderia chamar um método de cópia do construtor de cópia, mas não vice-versa.
Dito isso, se o seu objeto fornece uma função de troca otimizada, há um truque padrão que pode estar pensando em:
void List::copy(const List& aList)
{
List acopy(aList);
swap(*this, acopy);
}
Isto faz uma cópia do aList e troca então o conteúdo atual do seu objeto com esta cópia. ACOPY que agora tem o conteúdo de sua lista antes serão devidamente destruídas quando copiar retornos.
Finalmente, se você estiver indo para fazê-lo, a recomendação atual é na verdade ajustá-lo um pouco e escrevê-lo desta maneira:
void List::copy(List aList)
{
swap(*this, aList);
}
Sob certas circunstâncias, isso pode ser mais eficiente (e nunca é menos eficiente).
* - você pode fazer coisas estranhas e construir um objeto duas vezes com posicionamento novo. Mas não há nenhuma boa razão para fazer isso e muitas razões pelas quais não.
Outras dicas
Em seu programa de motorista, você tem
List bList;
bList.copy(aList);
Em vez disso, invocar o construtor de cópia com qualquer
List bList(aList);
ou
List bList = aList;
... Olhando para a sua "cópia" método: construtor Um cria uma nova instância. Seu método de Lista :: cópia chama o construtor de cópia, criar uma nova instância de lista na pilha. Em seguida, ele retorna, e sua nova instância é ido.
O que você provavelmente quer em vez de uma "cópia" método é definir um operador de atribuição,
List& List::operator=(const List& aList)
{
if (this != &aList)
{
// Do your copying here
}
return *this;
}
Em seguida, o motorista poderia dizer
List bList;
// ...Presumably manipulate bList in some other ways in-between...
bList = aList;
Para chamar o operador de atribuição de dentro de outro método da mesma classe, dizer
*this = aList;
ou
operator=(aList);
I encontrar o último estranho. Mas referindo-se a um operador explicitamente pelo nome pode ser necessário se você deseja obter um ponteiro para a função de membro.
Construtores são especiais porque eles são chamados de única quando o objeto é inicializado. Portanto, você não pode chamar qualquer como funções simples, copiar ou de outra forma. C ++ exige isso, porque ajuda a escrever código que quebra menos quando você adicionar recursos.
Provavelmente o que você quer é mover o corpo do construtor de cópia para Copy()
e Copy()
chamada de List::List(List const&)
.
A questão é, se essa sintaxe é tão fácil, então por que fazer um método copy
em tudo:> (a menos que você é uma daquelas pessoas que querem defensivas das cópias explicitamente - então eu apresentar, eu sou um deles também).
Você pode também estar interessado em fazer uma cópia (atribuição) operador em vez disso:
List& List::operator=(const List& aList)
{
//
}
Como para a incapacidade de chamar o construtor de cópia ver a C ++ FAQ Lite no Construtores . Este fio também faz a mesma pergunta.
A incapacidade de invocar construtores explicitamente de classe é uma parte do documento C ++ padrão, mas maaan, você não quer ler aquela coisa ... ainda; -)