Что такое сторожевой объект в C ++?

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

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

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

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

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

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


person Romain Hippeau    schedule 22.04.2010    source источник
comment
Помимо этого вопроса, скорее всего, это обман, пожалуйста, не помечайте свои вопросы какими-либо тегами, связанными с Visual Studio, когда задаете общие вопросы по C ++.   -  person P Shved    schedule 22.04.2010
comment
@Pavel Я искал и не нашел   -  person Romain Hippeau    schedule 22.04.2010
comment
@Pavel извини, это мой первый вопрос   -  person Romain Hippeau    schedule 22.04.2010


Ответы (2)


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

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

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

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

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

    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 */
  }
};
person P Shved    schedule 22.04.2010
comment
@Romian, без проблем, я изо всех сил стараюсь откладывать свою настоящую работу ›_‹ - person P Shved; 22.04.2010
comment
Разве мы все не знаем этого ... :) - person sbi; 23.04.2010

Отличие от АОП в том, что это нужно делать совместно, явно помещая часового где-нибудь внутри тела функции или определения класса.

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

person fa.    schedule 22.04.2010