Виртуальные деструкторы должны быть общедоступными? - программирование
Подтвердить что ты не робот

Виртуальные деструкторы должны быть общедоступными?

Я обнаружил, что почти каждый фрагмент кода виртуальных деструкторов имеет его как публичную функцию-член, например:

class Base
{
public:
    virtual ~Base()
    {
        cout << "~Base()" << endl;
    }
};
class Derived : public Base
{
public:
    ~Derived()
    {
        cout << "~Derived()" << endl;
    }
};

Должны ли виртуальные деструкторы быть общедоступными или существуют ситуации, когда имеет смысл непартийный виртуальный деструктор?

4b9b3361

Ответ 1

Должны ли виртуальные деструкторы быть общедоступными или существуют ситуации, когда имеет смысл непубличный виртуальный деструктор?

Лошади для курсов. Вы используете виртуальный деструктор public, если вам требуется полиморфное удаление, если нет, то ваш деструктор вообще не должен быть виртуальным.

Следуйте рекомендациям Herb:

Руководство № 4: Деструктор базового класса должен быть открытым или виртуальным, или защищенным и не виртуальным.

Вкратце, тогда у вас остается одна из двух ситуаций. Либо:

  • Вы хотите разрешить полиморфное удаление с помощью базового указателя, и в этом случае деструктор должен быть виртуальным и общедоступным; или
  • У вас нет, и в этом случае деструктор должен быть не виртуальным и защищенным, последним для предотвращения нежелательного использования.

Ответ 2

Подобно не виртуальным деструкторам, они не должны быть public, но большую часть времени они есть.

Если ваш класс является исключением из правила и для какой-либо причины должен контролировать время жизни своих экземпляров, то деструктор должен быть не public. Это повлияет на то, как клиенты могут (или не могут) использовать экземпляры класса, но это, конечно, все. А поскольку деструктор virtual, единственным другим вариантом будет virtual protected.

Связано: Используется ли для создания защищенного деструктора виртуального?

Ответ 3

Если вы планируете создавать/уничтожать объекты с помощью специальных методов (например, create/destroy), это необязательно. Но если вы создаете свой объект в стеке или куче, вы должны иметь публичный деструктор.

Ответ 4

Это зависит, во многих случаях ДА это должно быть общедоступным. Если деструктор написал в частном разделе, вам нужно создать экземпляр его указателями.

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

Ответ 5

Здесь речь идет о виртуальном деструкторе, поэтому я предполагаю, что перестановки причин, по которым такая реализация необходима, должны также включать случаи наследования. Ответ на вопрос зависит от следующего:

1) Вы можете использовать частный конструктор/деструктор, если вы не хотите, чтобы класс был создан. Хотя, экземпляр может быть выполнен другим методом в том же классе. Поэтому, когда вы хотите использовать в классе определенный метод, например MyDestructor(), чтобы вызвать деструктор, деструктор все равно может быть помещен в закрытый. Для примера: шаблон дизайна Singleton. Кроме того, в этом случае он предотвращает наследование класса

2) Если вообще предполагается, что класс наследуется, деструктор частного базового класса нельзя разрешить (генерирует ошибку компиляции). Но защищенный деструктор базового класса позволяет наследование

3) Тип наследования (открытый и защищенный) защищенного виртуального деструктора позволяет безопасный способ многоуровневого наследования A- > B- > C, так что, когда вызывается деструктор C, память очищается лучше.

4) Только частный деструктор не может разрешить удаление (я не уверен в auto_ptr, но я думаю, что даже это должно придерживаться той же мысли об использовании деструктора "private"), когда память динамически распределяется с использованием новых.

Вокруг, я вижу, использование частного деструктора может быть подвержено ошибкам, особенно когда кто-то, кто не знает о такой реализации, собирается использовать такой класс.

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

Надеюсь, это пояснит.

Ответ 6

Здесь задействованы два отдельных правила. Во-первых, если ваш проект требует удаления объектов производного типа с помощью указателя на базу, деструктор в базе должен быть виртуальным. Во-вторых, если функция-член (и тем самым я включаю деструктор в целом) защищена или закрыта, контексты, в которых она может быть вызвана, более ограничены, чем когда она открыта (конечно, если деструктор является закрытым, t, полученных из класса). Например:

class C {
protected:
    virtual ~C();
    friend void destroy_me(C*);
};

void destroy_me(C *cp) {
    delete cp; // OK: destructor is accessible
}

void destroy_someone_else(C *cp) {
    delete cp; // Error: destructor is not accessible
}