Он будет делать то же самое (ничего, по существу). Но это не то же самое, что если бы вы этого не пишете. Поскольку для записи деструктора потребуется рабочий деструктор рабочего класса. Если деструктор базового класса является закрытым или если есть какая-либо другая причина, он не может быть вызван, значит, ваша программа неисправна. Рассмотрим этот
struct A { private: ~A(); };
struct B : A { };
Это нормально, до тех пор, как ваш, не требуют, чтобы уничтожить объект типа B (и, таким образом, неявно типа А) - как если бы вы никогда не называйте удалить на динамически созданный объект, или вы никогда не создаете его объект в первую очередь. Если да, то компилятор отобразит соответствующую диагностику. Теперь, если вы предоставите один явно
struct A { private: ~A(); };
struct B : A { ~B() { /* ... */ } };
Это один будет пытаться неявно вызвать деструктор базового класса, и будет вызывать диагностическое уже во время определения в ~B
.
Существует еще одно отличие, которое сосредотачивается на определении деструктора и неявных вызовах деструкторов участника.Рассмотрим этот умный член указатель
struct C;
struct A {
auto_ptr<C> a;
A();
};
Давайте предположим, что объект типа C
создается в определении конструктор в файле .cpp
, который также содержит определение структуры C
. Теперь, если вы используете struct A
и требуете уничтожения объекта A
, компилятор предоставит неявное определение деструктора, как в случае выше. Этот деструктор также неявно вызывает деструктор объекта auto_ptr. И это удалит указатель, который он удерживает, что указывает на объект C
- не зная определения C
! Это появилось в файле .cpp
, где определен конструктор структуры A.
Это на самом деле общая проблема при реализации идиомы pimpl. Решение состоит в том, чтобы добавить деструктор и предоставить пустое определение его в файле .cpp
, где определена структура C
. В то время, когда он вызывает деструктор своего члена, он тогда узнает определение struct C
и может правильно вызвать его деструктор.
struct C;
struct A {
auto_ptr<C> a;
A();
~A(); // defined as ~A() { } in .cpp file, too
};
Обратите внимание, что boost::shared_ptr
не имеет этой проблемы: Вместо этого он требует полного типа, когда его конструктор вызывается определенным образом.
Еще один момент, когда он имеет значение в текущем C++, - это когда вы хотите использовать memset
и друзей на таком объекте, у которого есть объявленный пользователем деструктор. Такие типы больше не являются POD (простые старые данные), и они не могут быть скопированы. Обратите внимание, что это ограничение на самом деле не требуется - и следующая версия C++ улучшила ситуацию на этом, так что она позволит вам копировать все такие типы до тех пор, пока не будут сделаны другие более важные изменения.
С тех пор как вы попросили конструкторов: Ну, для них почти все то же самое верно. Обратите внимание, что конструкторы также содержат неявные вызовы деструкторам. В таких вещах, как auto_ptr, эти вызовы (даже если они не выполняются во время выполнения - чистая возможность уже здесь имеет значение) будут иметь тот же самый вред, что и для деструкторов, и происходят, когда что-то в конструкторе бросает - тогда компилятор должен вызвать деструктор членов. This answer использует неявное определение конструкторов по умолчанию.
То же самое верно и для видимости и PODness, которые я сказал о деструкторе выше.
Существует одна важная разница в отношении инициализации. Если вы поместите объявленный конструктор пользователя, ваш тип больше не получит инициализацию значений членов, и ваш конструктор должен выполнить любую инициализацию. Пример:
struct A {
int a;
};
struct B {
int b;
B() { }
};
В этом случае следующее всегда верно
assert(A().a == 0);
Хотя следующее неопределенное поведение, потому что b
никогда не был инициализирован (ваш конструктор опущен, что). Значение может быть равно нулю, но может также быть любым другим странным значением. Попытка прочитать из такого неинициализированного объекта вызывает неопределенное поведение.
assert(B().b == 0);
Это также верно и для использования этого синтаксиса в new
, как new A()
(обратите внимание на круглые скобки в конце - если они опущены инициализации значение не будет сделано, и так как там ни один пользователь не объявлен конструктор, который может инициализировать его , a
будет оставлен неинициализированным).
Я немного изменил этот вопрос, чтобы превратить редактирование afterthoguht в фактическую часть вопроса. Если есть какие-то синтаксические ошибки в тех частях, которые я редактировал, кричите на меня, а не на оригинального. @ Андрю, если вы чувствуете, что я слишком сильно изменил ваш вопрос, не стесняйтесь его возвращать; если вам нравится изменение, но думаю, что этого недостаточно, вы, очевидно, можете отредактировать свой собственный вопрос. –