Что такое деструктор с указателем друга? - PullRequest
3 голосов
/ 15 июня 2019

Я просматривал страницу cppreference о деструкторах и заметил два места, которые, кажется, указывают на существование друга-деструктора.

decl-specier-seq - друг , встроенный, виртуальный или ничего (без типа возврата)

...

В области имен или в объявлении friend в другом классе ...

Концепция друга-деструктора не имеет для меня абсолютно никакого смысла, и я никогда не видел этого на практике. Я надеялся, что кто-нибудь сможет прояснить это и объяснить, почему у деструктора будет когда-либо спецификатор друга, и как это будет выглядеть.

Ответы [ 3 ]

5 голосов
/ 15 июня 2019

Вы должны посмотреть описание для id-выражения ниже decl-specier-seq . Вы можете объявить деструктор для другого класса другом.

class AClass;

class classB {
public:
    AClass *a;
    ~classB();
};

class AClass {
    friend classB::~classB();
    ~AClass();
};

classB::~classB() {
     delete a;
}

В этом надуманном примере без объявления friend classB не сможет уничтожить содержащийся AClass объект.

Все обычные преимущества дружбы - например, возможность доступа к частным и защищенным членам класса - также будут применяться, так что это даст деструктору для classB доступ к любому частному или защищенному члену AClass.

0 голосов
/ 15 июня 2019

Чтобы добавить ответы, уже приведенные с точки зрения дизайна:

Каждый раз, когда вы хотите, чтобы какой-то другой класс был responsible для жизненного цикла объектов вашего класса (A) или для предотвращения разрушения объекта, dtor должен быть закрытым.

Закрытый dtor не позволит никому другому удалить его, кроме класса responsible. Метод deleter или dtor ответственного класса теперь должен быть другом класса A, чтобы иметь доступ к этому приватному dtor.

Варианты использования: подсчет ссылок или управление подключением к базе данных. поэтому класс responsible примет запрос к delete / disconnect вашего объекта и примет соответствующее решение.

Вот почему friend dtor удобен.

0 голосов
/ 15 июня 2019

Согласно стандарту ([class.dtor] / 1) вам разрешается использовать ключевое слово friend при объявлении деструктора:

Каждый decl-спецификатор из decl-specier-seq декларации деструктора (если есть) должен быть friend, inline или virtual.

(Примечание: в C ++ 20 вы также сможете объявлять деструкторы constexpr.)

Однако вы не можете просто взять обычное объявление деструктора в своем классе и добавить friend, например,

struct S {
    friend ~S();
};

Это не работает, потому что (я полагаю, но не могу найти стандартную кавычку для резервного копирования прямо сейчас), когда вы объявляете функцию другом, компилятор ищет имя в содержащем пространстве имен и, если он не найдет его там, сделает функцию членом этого пространства имен.

Тем не менее, что-то вроде этого совершенно правильно:

struct S { ~S(); };
struct T {
    // ...
    friend S::~S();  // this is also a declaration of S's destructor
};

Это позволяет деструктору S получать доступ к закрытым членам T, как и следовало ожидать.

...