2015-09-03 5 views
3

Я новичок в объектно-ориентированном программировании, и это может быть глупый вопрос, но я не понимаю, почему код класса A лучше использовать, чем класс B, если вы хотите создать копию одного объекта.Каковы преимущества использования конструктора копирования?

class A { 
    int num; 
public: 
    A(const A &ref) : num(ref.num) {}; 
}; 

class B { 
    int num; 
public: 
    B(B *ptToClass) : num(ptToClass->num) {}; 
}; 

Если бы я получил это право, конструктор копирования используется в классе А.

+0

http://stackoverflow.com/a/18611518/1012759 категорически запрещено принимать указатели. – CyberGuy

+3

@CyberGuy Этот вопрос говорит «скопировать объект», а не «создать конструктор копирования». Вы можете «скопировать объект» без конструктора копирования. – Yakk

+1

Вы уверены, что класс А лучше? Эти два класса выглядят довольно похожими на меня, один с бессмысленным конструктором копии, а другой с загадочным конструктором, который принимает указатель. – anatolyg

ответ

4

класса А является гибким и безопасным: вы создаете копию с любой объект вы, даже если это временный.

Класс B менее безопасен, так как вы могли бы вызвать конструктор с помощью nullptr. Это менее гибко, потому что вы можете использовать конструктор ypur только для копирования объекта, из которого вы можете получить адрес и который не является константой.

B b1(...);   
const B b2(...); 
B fb();  // function returning a B 

B b3(&b1);  
B b4(&b2);  // error b2 is const 
B b5(&fb()); // error you can't take adress of a temporary 
+0

Первое, что касается B, истинно, второе - нет (потому что 'B' имеет неявно определенный конструктор копирования, а также конструктор, переводящий указатель, поэтому он все равно может быть скопирован) –

+0

@JonathanWakely Конечно! Извините за мою плохую формулировку: я имел в виду конструктор, который был предоставлен для B, а не для реального конструктора копирования. Я отредактировал. – Christophe

0

запрещено стандартом использовать указатели в копии конструкторами:

C++ проект стандарта n3376 - раздел 12.8.2:

Конструктор без шаблона для класса X является копией конструктор, если первый его параметр имеет тип X &, const X &, летучий X & или const volatile X &, и ни один другой параметр eters или иначе все остальные параметры имеют стандартные аргументы

Why is the argument of the copy constructor a reference rather than a pointer?

+2

Но конструктор B не является конструктором копирования, поэтому все в порядке. –

2

Дело в том, что если конструктор считается конструктор копирования компилятором, он используется в специальных способов. Например, если у вас есть функция, которая принимает параметр типа вашего A копии, как это:

void function(A obj) { 
    // Do something with A 
    // ... 
} 

И тогда вы называете эту функцию:

int main() { 
    A a_obj; 
    function(a_obj); 
} 

объекта obj, полученного function будет создайте созданный вами экземпляр копии. Таким образом, неплохо предоставить конструктор копий для ваших классов, предназначенных для копирования, чтобы они лучше соответствовали языковым функциям и библиотекам.

Нет никакой проблемы при создании конструктора такого типа в вашем class B, если это соответствует вашим потребностям в вашем приложении, но это не будет понято компилятором как конструктор копирования и не будет использоваться, если компилятор или библиотеки должны копировать ваши объекты.

5

Если вы не объявите конструктор копирования для своего класса, компилятор будет объявлять его для вас в любом случае. Классы должны иметь копии конструкторов. Они запекаются на языке и имеют особый статус. Без них язык не работает.

Возможно, лучшим примером является то, что конструкторы копирования необходимы при передаче по значению. Компилятор будет неявно вызывать конструктор копирования при передаче по значению. Он не будет вызывать конструктор B::B(B*).

Итак, если вы хотите, чтобы ваш класс был доступен для копирования, вы должны определить логику копирования в конструкторе копирования. Это просто проще.

+0

«Классы ** должны иметь ** конструкторы копирования». На самом деле, нет. Я действительно не помню, в какой ситуации компилятор не будет генерировать для вас конструкторы копирования, но с C++ 11 вы можете явно удалить конструктор копирования. 'std :: unique_ptr' не имеет конструктора копирования. – lvella

+1

@ Ивелла У него все еще ** есть ** конструктор копирования, и это важно. Если вы попытаетесь скопировать 'std :: unique_ptr', он выберет конструктор копирования для копии, а затем вы получите сообщение об ошибке, так как оно будет удалено. – Brian

+1

Я думаю, что определение «иметь» здесь немного растянуто ... – lvella

Смежные вопросы