2012-02-10 3 views
0

У меня есть эти классы:Конструкторы копирования в C++

первый:

class C 
{ 
    public: 
    C(const C& c):_s(c._s){} 
    c():_s(""){} 

    string _s; 
} 

второй:

class C2: public C 
{ 
    public: 
    C2(const C2 & c2):_i(c2.i){} 
    C2():_i(0){} 

    int _i; 
} 

основные:

int main() 
{ 
    C2 c2; 
    C2._s="hello"; 
    c2._i=42; 
    C2 c3(c2); 
    cout<<c3._s<<" "<<c3._i<<endl; 
} 

и выход 42. Мой вопрос в том, почему выход 42? Базовый конструктор всегда вызывается перед производными конструкторами, так что эта строка:

C2 c3(c2); 

должен вызывать C конструктор копирования и должен копировать „привет“, имея в виду выход должен быть привет. Что я упускаю здесь?

+0

Ваш код неправильный - вы смешиваете свои дела, а ваши подчеркивания также ошибаются. – Arafangion

ответ

4

Причина в том,

C2(const C2 & c2):_i(c2.i){} 

не инициализирует _s к значениям, сохраненным в c2, поскольку по умолчанию (без параметров) конструктор базового класса вызывается, если не указано иное, и поэтому _s также инициализируется конструктором по умолчанию , а не конструктор копирования.

В частности, в вашем случае C2::(const C2&) вызывает C::C() и вызывает string::string().

Вы должны явно вызвать правильный базовый конструктор:

C2(const C2 & c2) : 
    C(c2), 
    _i(c2.i) 
{ 
} 
+0

Вы должны инициализировать базу перед выводом членов. –

+1

@Ed Heal: Я исправил это, но знаете ли вы, что это не влияет на поведение? – sharptooth

+0

Это можно сделать.Известно, что статические функции-члены, отвечающие в базовом классе, используются в инициализационных списках для инициализации полученных членов. –

0

Да, базовый класс вызывается перед производным классом, WHICH конструктор базового класса вызывается, однако, зависит от спецификации производного класса.

1

Помимо опечатки (строку s-> строку _s), копию конструктор производного класса должен вызвать конструктор для базового класса

т.е.

C2(const C2 & c2):C(c2), _i(c2.i){} 

BTW - вопрос будет легче с меньшим количеством подобных имен для типов в качестве переменных

1

Вызывается конструктор копирования для объекта. Созданный по умолчанию (компилятор 10) сгенерированный конструктор копирования вызывает конструктор копирования для каждого члена, , затем конструктор копирования для каждого базового класса. Конструктор копирования , написанный вами, делает именно то, что вы написали, не больше, не меньше. Большинство во времени, определенный пользователем конструктор копирования должен начать копию построения своих баз:

C2::C2(C2 const& other) 
    : C(other) 
    , _i(other._i) 
{ 
} 

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

+0

Разве это не «конструктор копирования для каждого базового класса, а затем для конструктора копирования для каждого члена»? У меня создалось впечатление, что базовые классы были инициализированы перед членами. –

+0

@CharlesBailey Да. На самом деле существует очень строгий порядок, который сначала создает виртуальные базы, в порядке их видимости при первом посещении графа наследования слева направо, а затем не виртуальные базы, слева направо, поскольку они появляются в классе определение, затем члены, снова слева направо. –

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