Что такое "сторожевой объект" на С++?

I ответил на этот вопрос и Potatoswatter ответил также как

Современный эквивалент С++ был бы сторожевой объект: постройте его на начало функции, с ее конструктор, реализующий вызов(), и по возвращении (или аномальному выходу), его деструктор реализует

Я не знаком с использованием часовых объектов в С++. Я думал, что они ограничены входными и выходными потоками.

Может ли кто-нибудь объяснить мне о сторожевых объектах С++, а также как использовать их в качестве перехватчика для одного или нескольких методов в классе?

то есть. Как это сделать?

Объекты Sentry очень похожи в самом деле. С одной стороны, они требуют явное инстанцирование (и прошло это), но, с другой стороны, вы может добавить к ним, чтобы они не проверяли только инварианты класса, но некоторые предварительные условия для функции под рукой.

Ответы

Ответ 1

Объект Sentry - это шаблон, но я не уверен, какой из них ниже (возможно, все).

Программы на С++ часто сильно зависят от знания, когда уничтожается именно объект (возможно, определенный пользователем класс), т.е. когда его деструктор вызывается. Это не относится к языкам с сборкой мусора.

Этот метод используется, например, для использования парадигмы "Инициализация ресурсов": вы приобретаете ресурсы при вызове конструктора объектов, а компилятор автоматически вызывает его деструктор для освобождения ресурсов как в нормальных, так и в ненормальных (исключительных) ситуациях (проверьте этот вопрос).

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

  • Блоки: деструктор для объекта с выделенным стекем вызывается в конце блока

    void function()
    {  Class foo = Object(resource);
       other_operations();
    }  // destructor for foo is called here
    
  • Вызов функций: "распределение стека" также происходит, когда вы вызываете функцию

    void function()
    {  another_function ( Class(resource)  );
       // destructor for the unnamed object is called
       // after another_function() returns (or throws)
       other_operations();
    }
    
  • Конструирование/уничтожение содержащего объекта:

    class Foo
    {  Class sentry;
       public: Foo()
       { // Constructor for sentry is called here
          something();
       }        
       public: ~Foo()
       {
          something();
       }  // destructor for sentry is called here
    };
    

В STL есть класс под названием sentry (точнее, istream::sentry), который реализует третий шаблон описанных выше. Поэтому я думаю, что некоторые программисты называют "сторожевым объектом".

Но на самом деле любой из вышеуказанных объектов класса Class можно назвать "сторожевым объектом". Они "часовые", потому что они гарантируют, что эти неуправляемые деструкторы объектов не будут упущены, даже если что-то выдает исключение (так что они похожи на опекунов блока/класса).

Другие примеры объектов-часовых находятся в этом вопросе RAII.


Вы можете видеть отношение к аспектно-ориентированному программированию; эти объекты являются чем-то вроде "аспектов", с точками "в начале/конце закрывающего блока", "при построении/уничтожении содержащего объекта" и т.д. Но эти "аспекты" должны присутствовать в коде, который они апроксируют. Таким образом, они менее "аспектны" по сравнению с оригинальной функциональностью call/return; вместо этого в каждую функцию класса должен быть вставлен часовой объект:

class X{
  struct Sentry {
     Sentry() { /* call() */}
    ~Sentry() { /* return() */};
  };

  void member_function()
  { Sentry();
    /* operations */
  }

  void another_member_function()
  { Sentry();
    /* operations */
  }
};

Ответ 2

Разница с AOP заключается в том, что она должна выполняться совместно, помещая часовое явно где-то внутри тела функции или определения класса.

Вы не можете перехватывать вызовы без изменения целевой функции или класса.

Ответ 3

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