Конструктор копирования не наследуется
У меня есть следующий код:
class C {
public:
C(int) {}
C(const C&) {}
C() {}
};
class D : public C {
public:
using C::C;
};
int main() {
C c;
D d_from_c(c); // does not compile, copy ctor is not inherited
D d_from_int(1); // compiles, C(int) is inherited
}
Производный класс должен наследовать все ctors базы, кроме значения по умолчанию ctor (объясняется здесь). Но зачем копировать ctor тоже не унаследовано? Аргументы из связанного с этим вопроса здесь неприемлемы.
Код компилируется с помощью g++ 4.8.1.
Ответы
Ответ 1
Потому что стандарт говорит так. [class.inhctor]/p3, основное внимание:
Для каждого конструктора без шаблона в наборе кандидатов унаследованных конструкторы , кроме конструктора, не имеющего параметров или copy/move, имеющий единственный параметр, конструктор неявно объявляется с теми же характеристиками конструктора, если только есть конструктор с объявленным пользователем с той же сигнатурой в полный класс, где появляется декларация использования или конструктор будет конструктором по умолчанию, копией или перемещением для этого класса.
Ответ 2
Производный класс должен наследовать все ctors базы, за исключением значения по умолчанию ctor
Нет, это не так, см. T.C. answer для реального правила.
Цель наследования конструкторов - сказать, что "производный тип может быть создан из тех же аргументов, что и базовый тип", но это не относится к конструктору копии базового класса, поскольку конструктор копирования - это не просто способ сказать, как создать тип из заданного аргумента.
Конструктор копирования является специальным, он предназначен для копирования объекта того же типа.
Конструктор D(const C&)
не использовался бы для копирования объекта того же типа, потому что C
не является тем же типом, что и D
.
Ответ 3
На какое-то время предположим, что допустимо наследование конструктора экземпляров.
Если ваша структура классов не повреждена, рассмотрите следующий код для модифицированного основного метода.
int main() {
C c;
D d;
D d_from_d(d);
D d_from_c(c); // does not compile, copy ctor is not inherited
D d_from_int(1); // compiles, C(int) is inherited
}
В D d_from_d(d)
, как обычный вызов конструктора, будут два вызова конструктора копий. Один для C:: C (const C &), а другой - для созданного компилятором конструктора копии для D. Имея тип исходного объекта в D (d в этом случае), конструктор Cs copy может копировать атрибуты ds C при генерировании компилятора Ds copy конструктор может копировать атрибут ds D.
Но в случае D d_from_c(c)
Нет проблемы для конструктора Cs copy, потому что атрибуты cs C могут быть экземплярами с помощью конструктора Cs copy. Но как создатель компилятора, созданный конструктором Ds, знает способ копирования атрибутов Ds из объекта Cs. Это конфликт, которого следует избегать.
Но если вы предоставили какой-то "странный конструктор копирования" (возможно, вам понадобится также конструктор по умолчанию), например:
D(const C & c):C(c){}
Тогда,
вызов D d_from_c(c);
действует. Потому что теперь мы явно предоставили соответствующий "конструктор копирования".
Таким образом, использование разрешений "Унаследованные копии" недействительно.