У меня длинный урок с большим количеством участников. Я хочу написать конструктор копирования для него. Но если я напишу свой собственный конструктор копирования, я потерял доступ к конструктору по умолчанию.
Я просто хочу исправить несколько указателей в моем собственном конструкторе копирования. Поэтому я хочу иметь мелкую копию объекта, которая может быть сделана по умолчанию конструктором копирования.
Есть ли возможность получить доступ к конструктору копирования по умолчанию, когда уже есть мой собственный конструктор копирования?
Оберните вещи, которые вы не хотите изменять, в структуру и извлекайте из нее (в частном порядке). В вашем конструкторе копирования просто вызовите конструктор копирования вашего базового класса.
Нет, вы не можете иметь как по умолчанию, так и свой собственный экземпляр c-tor.
Но есть два обходных пути с этой проблемой:
1 Заключите ваши указатели в некоторый класс с определенной семантикой копирования
Пример:
class A {
public:
private:
int trivial1;
int trivial2;
...
SomePointer nontrivialMember;
};
class SomePointer {
public:
SomePointer(const SomePointer&); // here the non trivial part of A copy semantics
int* nonTrivialMember;
};
2 Заключите тривиальные параметры в некоторую тривиальную структуру
Пример:
class A {
public:
A(const A& o) : data(o.data) {
// non trivial part
}
private:
struct Data {
int trivial1;
int trivial2;
...
} data;
int* nontrivialMember;
};
Я бы всегда выбрал первое решение.
[ОБНОВИТЬ]Существует также третье решение, очень похожее на мое второе, заключающее вашу тривиальную часть в частный унаследованный базовый класс. Я бы все же предпочел 1-е решение.
Простейшим подходом к этому было бы заключить указатели в классы, которые будут выполнятьремонт‘вручную в их конструкторе копирования, тогда вы можете с радостью использовать конструктор копирования по умолчанию.
Нет, нет способа вызвать конструктор копирования по умолчанию из определяемого пользователем конструктора копирования.
Вы можете использовать по умолчанию или свой собственный, но не оба. Если вы хотите выбрать разные функциональные возможности для разных объектов, вам просто нужно написать функцию-член, которая обрабатывает этот случай.
void DeepCopy(MyClass* rhs);
Например.
Вы не можете получить доступ к копии по умолчанию ctor, если создали свой собственный — компилятор просто не генерирует его. Но есть обходной путь — разделите ваш класс на структуру данных и логику.
Смотрите пример:
struct Data
{
int i;
std::string s;
Data(): i(), s() {}
};
class Code: private Data
{
public:
Code() {}
Code(const Code& rhs): Data(rhs) // Call default copy ctor
{
i = 42; // Your copy part
return *this;
}
};
Мое решение — простой memcpy () вместо невозможного вызова неявного (сгенерированного компилятором) конструктора копирования, как показано в примере ниже:
Class Foo
{
public:
...
Foo (Foo & other) {
// copies trivial part (and non-trivial part with possible wrong values)
memcpy(this, &other, sizeof(Foo));
// your non-trivial part here, overwrites the wrong values (if any) above.
}
}
Тем не менее, побочным эффектом является то, что memcpy () также скопирует эту нетривиальную часть, которая является пустой тратой. Если нетривиальная часть не содержит слишком много места, я предпочту свое решение.
Например, класс, подобный приведенному ниже, тратит только 4-байтовую копию одного указателя, предполагая, что размер указателя составляет 4 байта.
Class Bar
{
int x, y, z;
// memcpy() wastes these 4 bytes copy,
// since actual copy constructor wants a new string
string *s;
}
Это сработало для меня … (C ++ 11, не знаю, работает ли оно на старых std)
Не уверен, почему это не заканчивается бесконечной петлей.
class Foo {
public:
Foo(const Foo &orig) {
*this = orig;
... exchange pointers, do own stuff
}