Ответ 1
Вам не нужно явно объявлять деструктор в производном классе:
§ 15.4 Деструкторы [class.dtor] (выделено мной)
Деструктор может быть объявлен виртуальным (13.3) или чисто виртуальным (13.4); если любые объекты этого класса или любого производного класса создаются в программа, деструктор должен быть определен. Если класс имеет базовый класс с виртуальным деструктором, его деструктором (будь то user- или неявно объявленный) является виртуальным.
Фактически, в некоторых случаях это может даже нанести ущерб производительности, поскольку явное объявление деструктора предотвратит неявную генерацию конструктора перемещения и оператора присваивания перемещения.
Если вам не нужно что-то делать в своем деструкторе, лучшим способом будет просто пропустить явное объявление деструктора.
Если вам нужен собственный деструктор, и вы уверены, что копирование ctor по умолчанию, оператор присваивания копий, ctor перестановки и оператор присваивания перемещений будут делать для вас правильную вещь, лучше всего явно указать их по умолчанию следующим образом:
MyError(const MyError&) = default;
MyError(MyError&&) = default;
MyError& operator=(const MyError&) = default;
MyError& operator=(MyError&&) = default;
Несколько рассуждений о том, почему вы видите ошибку, потому что раньше это был правильный код в С++ 98:
Начиная с С++ 11 неявная генерация конструктора копирования объявлена устаревшей.
§ D.2 Неявное объявление функций копирования [depr.impldec]
Неявное определение конструктора копирования по умолчанию не рекомендуется, если у класса есть user- объявленный оператор присваивания копии или user- объявлен деструктором. Неявное определение копии оператор присваивания по умолчанию считается устаревшим, если класс имеет user- объявленный конструктор копирования или user- объявленный деструктор (15.4, 15.8). В будущем пересмотре этого международного стандарта эти неявные определения могут быть удалены (11.4).
Обоснованием этого текста является хорошо известное правило трех.
Все приведенные ниже цитаты получены из cppreference.com: https://en.cppreference.com/w/cpp/language/rule_of_three
Правило трех
Если классу требуется определенный деструктор user-, определенная копия user- конструктор, или user- определенный оператор присваивания копии, это почти безусловно, требует всех трех.
Причина, по которой существует это практическое правило, заключается в том, что по умолчанию генерируемые dtor, copy ctor и оператор присваивания для обработки различных типов ресурсов (в первую очередь указатели на память, но также и другие, такие как файловые дескрипторы и сетевые сокеты, чтобы назвать только пару) редко сделать правильное поведение. Если программист подумал, что ему нужна специальная обработка для закрытия дескриптора файла в деструкторе класса, он наверняка захочет определить, как этот класс должен быть скопирован или перемещен.
Для полноты ниже приводятся часто связанные правила 5 и несколько оспариваемое правило нуля
Правило пяти
Поскольку наличие деструктора, определенного user-, конструктор копирования, или оператор копирования-назначения предотвращает неявное определение перемещения конструктор и оператор присваивания перемещения, любой класс, для которого выполняется перемещение семантика желательна, должна объявить все пять специальных членов Функции:
Правило нуля
Классы, которые имеют собственные деструкторы, конструкторы копирования/перемещения или операторы копирования/перемещения должны иметь дело исключительно с правами собственности (что следует из принципа единой ответственности). Другие классы не должны иметь пользовательских деструкторов, конструкторов копирования/перемещения или операторы копирования/перемещения.