如何检查一个函数是不是被另一个函数调用?
Posted
技术标签:
【中文标题】如何检查一个函数是不是被另一个函数调用?【英文标题】:How can I check a function was called by another function?如何检查一个函数是否被另一个函数调用? 【发布时间】:2011-07-01 08:32:49 【问题描述】:我目前正在尝试确保一个类的成员函数仅被另一个类的成员函数调用。
架构是强加的,无法更改,端口意味着在调用b.call()
之前必须在a.call()
中完成一些逻辑。 a.call()
因此调用 b.call()
来简化事情并确保遵守顺序。
我在我的问题中找到了this answer。只是,问题是我正在使用类,并且这两个类具有 same 成员函数名称,因此 #define
尝试替换所有具有不同原型的事件。
【问题讨论】:
【参考方案1】:我推荐passkey pattern。它非常适合对谁可以对您的函数执行什么操作进行细粒度控制。
【讨论】:
这真的很酷。我不会想到的。 @Xeo:哦,这是个好名字,一年前我们挣扎过,没人知道它的名字,我喜欢你的 :) @Space:我喜欢这种模式(尤其是 C++0x 版本),我会尽可能地传播信息。 :) @Matthieu:如果您查看该问题的 OP 问题,则应该有一个要求名称(或相关问题之一),这是公认的答案。 :) 编辑:Here it is. @Xeo:是的,但是放弃朋友是一个不错的举动:)我提到的斗争是你链接的确切问题:)【参考方案2】:在我的脑海中,选项将是:
将b.call
设为私有,并将b
添加为a
或a.call
作为friend
将b.call
转换为一个类并将主体放入一个私有构造函数中,其中a
或a.call
作为friend
grep b.call
的源代码,确保唯一的调用在 a.call
,并在声明中添加注释“如果调用此函数,您将被解雇”
更改 b.call
以将其需要的至少一个值作为参数(即使它忽略它并使用其他地方的值)
【讨论】:
是的,第一个选项是我最后所做的。我会删除我的答案并接受你的。 @3nixios:请注意,现在a
中的每个 函数都可以调用b.call()
。
@Xeo 我同意这可能是有问题的,但它留下的错误调用b.call
的空间要小得多,虽然我的问题很具体,但这对我来说应该足够好了。谢谢。【参考方案3】:
您能否更改b.call
以引用a
?这样b.call
就可以调用a.call
本身了:
struct A
void call()
// do stuff
;
struct B
void call(A & a)
a.call();
// do stuff
;
这确保a.call
总是在b.call
的其余部分被执行之前被调用。
【讨论】:
+1 是的,保持依赖关系会很好,但我更喜欢使用 friend 类'cleaner'。 @3nixios:它们更干净,但是你陈述问题的方式,它们并没有完全解决它。朋友的任何方法都可以调用该方法,所以还是有调用顺序错误的可能。 @Space_C0wb0y 这是真的,但对于我的具体用途来说,目前这已经足够了。您的回答在全球范围内更容易接受,这就是我仍然投赞成票的原因。【参考方案4】:使用标志怎么样?
a.call()
// ...
flag = 1;
b.call();
flag = 0;
b.call()
if (flag == 0)
return;
// ...
【讨论】:
这需要在两个类之间共享一个标志,我觉得 vto 不太合我的口味。友元类提供的编译时检查也更合适。【参考方案5】:如果您为特定平台(例如 x86 或 x64)编程,并且您知道调用约定(例如 cdecl),那么您可以get this info from the stack
假设您要检查调用该函数的 对象,因此使用在调用成员函数之前压入堆栈的 this
指针:获取 this
指针并进行比较它与你想要的对象 (this_pointer == a
)
如果您想检查某个函数,请从堆栈中获取调用者地址并检查该函数:caller_address == A::call
。如果是虚函数,使用this
指针获取vtable
。
根据调用约定和将变量压入堆栈的顺序,您可能必须首先检查输入变量的大小,才能获得所需的信息。
【讨论】:
以上是关于如何检查一个函数是不是被另一个函数调用?的主要内容,如果未能解决你的问题,请参考以下文章
如何检查检查PInvoke签名的调用约定和参数与非托管的目标签名是不是匹配?