什么是“哨兵对象”?在 C++ 中?
现代 C++ 的等价物是 哨兵对象:构造它 函数的开头,及其 实现 call() 的构造函数,以及 返回(或异常退出)时,其 析构函数实现
我不熟悉在 C++ 中使用哨兵对象。 我认为它们仅限于输入和输出流。
有人可以向我解释一下 C++ 哨兵对象以及如何将它们用作类中一个或多个方法的周围拦截器吗?
即如何做到这一点?
Sentry 对象非常相似 的确。一方面他们要求 显式实例化(并且是 通过了这个)但另一方面你 可以添加到它们中,以便它们检查不 只有类的不变量,但是 一些前置/后置条件 手头的功能。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Sentry 对象是一种模式,但我不确定下面的哪一个(也许全部)。
C++ 程序通常严重依赖于知道对象(可能是用户定义的类)何时被销毁,即何时调用其析构函数。对于具有垃圾收集功能的语言来说,情况并非如此。
例如,该技术用于拥抱“资源获取即初始化”范例:在调用对象构造函数时获取资源,编译器会在正常和异常(异常)情况下自动调用其析构函数来释放资源(检查 < a href="https://stackoverflow.com/questions/712639/please-help-us-non-c-developers-understand-what-raii-is">这个问题)。
可以利用构造/销毁计时知识的常见位置是
块:在块的末尾调用“堆栈分配”对象的析构函数
函数调用:“stack-当您调用函数时也会发生分配”
包含对象的构造/销毁:
在STL中,有一个名为
sentry
的类(更准确地说,istream::sentry),它实现了上述的第三种模式。所以我认为这就是一些程序员所说的“哨兵对象”。
但事实上,上述
Class
类的任何对象都可以称为“哨兵对象”。它们是“哨兵”,因为它们确保即使有异常抛出,也不会错过这些难以捉摸的对象析构函数(因此它们就像块/类的守护者)。更多哨兵对象示例位于 RAII 问题。
您可以看到与面向方面编程的关系;这些对象类似于“方面”,具有“在封闭块的开始/结束处”、“在包含对象的构造/销毁时”等切点。但是这些“方面”必须存在于他们关注的代码。因此,与原始的
调用/返回
功能相比,它们的“视角”较少;相反,应该将哨兵对象插入到该类的每个函数中: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
Function calls: "stack-allocation" also happens when you call a function
Construction/Destruction of the containing object:
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:与 AOP 的区别在于,它必须通过将哨兵显式地放置在函数体或类定义内的某个位置来协作来完成。
如果不修改目标函数或类,您就无法捕获调用。
The difference with AOP is that it has to be done cooperatively by putting the sentry explicitly somewhere inside the function body or class definition.
You cannot catch the calls without modifying the targeted function or class.