Что “часовой является объектом” в C++?

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

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

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

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

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

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

14
задан Community 23 May 2017 в 12:08
поделиться

3 ответа

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

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

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

Общие места, где вы можете использовать информацию о времени построения / разрушения, - это

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

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

     void function () 
     {another_function (Class (resource)); 
     // вызывается деструктор для безымянного объекта {{1 }} // после того, как another_function () вернет (или выбрасывает) 
    other_operations (); 
    } 
     
  • Создание / уничтожение содержащего объекта :

     class Foo 
     {Class sentry; 
    public: Foo () 
     {// Здесь вызывается конструктор для часовой 
    something (); 
    } 
    public: ~ Foo () 
     {
    something (); 
    } // здесь вызывается деструктор для часового 
    }; {{1 }} 

В 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 */
  }
};
16
ответ дан 1 December 2019 в 12:51
поделиться

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

2
ответ дан 1 December 2019 в 12:51
поделиться

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

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

3
ответ дан 1 December 2019 в 12:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: