I answered this question, and Potatoswatter answered too as
The modern C++ equivalent would be a sentry object: construct it at the beginning of a function, with its constructor implementing call(), and upon return (or abnormal exit), its destructor implements
I am not familiar with using sentry objects in C++. I thought they were limited to input and output streams.
Could somebody explain to me about C++ sentry objects as well as how to use them as an around interceptor for one or more methods in a class ?
i.e. How to do this ?
Sentry objects are very similar indeed. On the one hand they require explicit instantiation (and being passed this) but on the other hand you can add to them so that they check not only the invariants of the class but some pre/post conditions for the function at hand.
Sentry objects are very similar indeed. On the one hand they require explicit instantiation (and being passed this) but on the other hand you can add to them so that they check not only the invariants of the class but some pre/post conditions for the function at hand.
sentry-native/0.5. 0 The Sentry Native SDK is an error and crash reporting client for native applications, optimized for C and C++. Sentry allows to add tags, breadcrumbs and arbitrary custom context to enrich error reports.
Sentry object is a pattern, but I'm not sure which one of those below (maybe all).
C++ programs often heavily rely on knowledge when exactly an object (possibly of a user-defined class) is destroyed, i.e. when its destructor is called. This is not the case for languages with garbage collection.
This technique is used, for example, to embrace "Resource Acquisition Is Initialization" paradigm: you acquire resources when an object constructor is called, and the compiler automatically calls its destructor to free resources in both normal and abnormal (exceptional) situations (check this question).
Common places where you can utilize the knowledge of construction/destruction timing are
Blocks: a destructor for "stack-allocated" object is called at the end of the block
void function()
{ Class foo = Object(resource);
other_operations();
} // destructor for foo is called here
Function calls: "stack-allocation" also happens when you call a function
void function()
{ another_function ( Class(resource) );
// destructor for the unnamed object is called
// after another_function() returns (or throws)
other_operations();
}
Construction/Destruction of the containing object:
class Foo
{ Class sentry;
public: Foo()
{ // Constructor for sentry is called here
something();
}
public: ~Foo()
{
something();
} // destructor for sentry is called here
};
In STL there's a class called sentry
(more exactly, istream::sentry
), which implements the third pattern of those described above. So I think that is what some programmers refer to as "sentry object".
But in fact any of the above objects of class Class
may be called "sentry object". They're "sentry" because they ensure that these elusive object destructors are not missed even if something throws an exception (so they are like guardians of the block/class, of sorts).
More sentry object examples are in that RAII question.
You can see a relation to aspect-oriented programming; these objects are something like "aspects", with cutpoints "at the beginning/ending of the enclosing block", "at construction/destruction of containing object" etc. But these "aspects" have to present in the code they aspectate. So they're less "aspective" compared to the original call/return
functionality; instead, a sentry object should be inserted to each function of the class:
class X{
struct Sentry {
Sentry() { /* call() */}
~Sentry() { /* return() */};
};
void member_function()
{ Sentry();
/* operations */
}
void another_member_function()
{ Sentry();
/* operations */
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With