2009-10-18 1 views
14

Нужно ли явно определять конструктор по умолчанию, когда мы определяем конструктор копирования для класса? Просьба привести причины.Копировать конструктор и конструктор по умолчанию

например:

class A 
{ 
    int i; 

    public: 
      A(A& a) 
      { 
       i = a.i; //Ok this is corrected.... 
      } 

      A() { } //Is this required if we write the above copy constructor?? 
};  

Кроме того, если мы определим любой другой параметризованный конструктор для класса, отличного от конструктора копии, мы также должны определить конструктор по умолчанию ?? Рассмотрим приведенный выше код без конструктора копирования и заменить его

A(int z) 
{ 
    z.i = 10; 
} 

Alrite .... После просмотра ответов я написал следующую программу.

#include <iostream> 

using namespace std; 

class X 
{ 
    int i; 

    public: 
      //X(); 
      X(int ii); 
      void print(); 
}; 

//X::X() { } 

X::X(int ii) 
{ 
    i = ii; 
} 


void X::print() 
{ 
    cout<<"i = "<<i<<endl; 
} 

int main(void) 
{ 
    X x(10); 
    //X x1; 
    x.print(); 
    //x1.print(); 
} 

И эта программа работает нормально без конструктора по умолчанию. Пожалуйста, объясните, почему это так? Я действительно смущен концепцией .....

+2

Я смущен. Хотя приведенный ниже ответ верен, это не конструктор копирования. Где вы копируете 'i', точно? Вы изменяете правую часть, что обычно неправильно. Вы должны делать 'A (const A & rhs): i (rhs.i) {}', то есть скопировать правую часть 'i' в этот экземпляр A' i'. Обратите внимание, что параметры передаются константой, потому что, когда вы говорите что-то вроде x = 3, 3 не следует изменять. Кроме того, обычно числовые типы передаются по значению, а не по ссылке, потому что ссылки могут быть медленнее для небольших типов данных. – GManNickG

+0

Wow .... Спасибо за ваш комментарий ... он очистил путаницу в отношении «: i (rhs.i)» части конструктора, который меня смутил, так как я начал изучать конструкторы этим утром .... –

+1

последняя программа не использует конструктор по умолчанию в любом месте. По этой причине вам не нужно ее определять. Вот и все. – AnT

ответ

33

Да. Как только вы явно объявляете абсолютно любым конструктором для класса, компилятор прекращает предоставление неявного конструктора по умолчанию. Если вам по-прежнему нужен конструктор по умолчанию, вы должны явно объявить и определить его самостоятельно.

P.S. Можно написать конструктор копирования (или конструктор преобразования или любой другой конструктор), который также является по умолчанию конструктором. Если ваш новый конструктор попадает в эту категорию, нет необходимости предоставлять дополнительный конструктор по умолчанию в малейшей :)

Например:

// Just a sketch of one possible technique  
struct S { 
    S(const S&); 
    S(int) {} 
}; 

S dummy(0); 

S::S(const S& = dummy) { 
} 

В приведенном выше примере конструктор копирования является одновременно конструктор по умолчанию ,

+0

«Можно написать конструктор копирования, который также является конструктором по умолчанию». Как? – dalle

+0

Добавляя, например, аргумент по умолчанию для копировального устройства. См. Пример, который я добавил в свой ответ. – AnT

+0

Не могли бы вы очистить мой отредактированный вопрос? Код работает отлично, не задавая конструктор по умолчанию. –

3

Вам не нужно определять оба параметра. Однако, как только вы определяете какие-либо конструкторы для класса, все значения по умолчанию становятся недоступными. Итак - если вы хотите как copy-construct, так и построить без копирования, вам нужно определить конструктор default (т.е. без явно заданных) по умолчанию (т.е. без параметров).

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

+0

Вы путаете проблему, перегружая слово «по умолчанию». Не только это, но и ваше перегруженное значение умолчания было объяснено словом «явным», которое является другим ключевым словом, зарезервированным для использования с конструкторами! Вместо этого вы можете использовать синтезированный (с z, если хотите). :) – Troubadour

+0

Перегрузка слова «default» была преднамеренной - просто грустно, что у вас нет смысла играть в слова. Что касается слова «явный» - существование специализированных значений в языке C++ не отменяет ранее существовавших значений в английском языке. А что касается «синтезированного» - я думал, что цель должна быть понята? – Steve314

1

Как сказал AndreyT, если вы явно объявляете какой-либо конструктор, включая конструктор копирования, компилятор не будет объявлять неявно или определять конструктор по умолчанию.

Это не всегда проблема.

Если вы не хотите, чтобы ваш класс был по-умолчанию конструктивным, то вполне нормально не объявлять конструктор по умолчанию. Но если вы хотите, чтобы он был конструктивным по умолчанию (например, если вы хотите раскомментировать строку X x1; в своем примере), вы должны объявить и определить конструктор по умолчанию.

Также обратите внимание, что конструктор по умолчанию - это любой конструктор, который может быть вызван без аргументов, а не только без аргументов. X::X(int = 5) - совершенно прекрасный конструктор по умолчанию.

0

1) Конструктор без аргумента называется конструктором по умолчанию. 2) Если пользователь не предоставил ни один из следующих конструкторов, компилятор объявит конструктор по умолчанию для вас.

2a) Copy Constructor 
    2b) Non-default constructor 
    2C) default constructor. 

3) Если компилятор объявляет «конструктор по умолчанию», то он, как говорят, «неявно объявлен конструктор по умолчанию»,

4) «неявно объявленный конструктор по умолчанию» бывают двух типов

4a) **trivial** Constructor 
    4b) **non-trivial** Constructor. 

5) неявно объявлен конструктор по умолчанию называется «тривиальной», когда есть 5а) Нет задающее 5б) Нет Функция Virtual 5с) Нет Virtual Base Class. 5d) класс Parent имеет 'тривиальный' конструктор,

Else, it is said to be 'non-trivial'. 

Надеется, что это помогает.

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

  • Нет связанных вопросов^_^