如何检查一个函数是否被另一个函数调用?

3

我目前正在努力确保一个类的成员函数仅被另一个类的成员函数调用。

架构是强制性的,不能改变,端口意味着在调用b.call()之前必须在a.call()中执行一些逻辑。因此,a.call()调用b.call()以简化事情并确保顺序得到尊重。

我发现了这个答案来回答我的问题。只是,问题在于我正在使用类,并且这两个类具有相同的成员函数名称,因此#define试图替换具有不同原型的所有出现。

5个回答

7

我推荐使用密码钥匙模式。这种模式非常适合对函数进行细粒度控制,使得谁可以以何种方式使用你的函数。


这真的很酷。我想不到那个。 - Björn Pollex
@Xeo:哦,这是个好名字,我们一年前也曾苦苦寻找,没人知道它的名字,我喜欢你们的 :) - Matthieu M.
@Space:我喜欢那个模式(尤其是C++0x版本),并且我会尽我所能传播这个消息。 :) - Xeo
@Matthieu:如果你查看那个问题的OP的问题,应该会有一个要求名称的问题(或者相关问题之一有它),那就是被接受的答案。 :) 编辑在这里 - Xeo
@Xeo:是的,但放弃朋友也是一个好举动 :) 我所指的斗争就是你链接的精确问题 :) - Matthieu M.

3

我能想到的方案如下:

  • b.call设为私有,使b添加aa.call作为friend
  • b.call变成一个类,并将其主体放入一个私有构造函数中,其中aa.call作为friend
  • 在源代码中搜索b.call,确保唯一的调用在a.call中,并在声明处添加注释,说明“如果你调用这个函数,你将被解雇”
  • b.call更改为至少将其需要的一个值作为参数传递(即使它忽略它并使用来自其他地方的值)

是的,最终我选择了第一个选项。我会删除我的答案并接受你的答案。 - 3nixios
@3nixios:请注意,现在 a 中的每个函数都可以调用 b.call() - Xeo
@Xeo 我同意这可能会有问题,但它减少了错误调用 b.call 的可能性,虽然我的问题很具体,但这对我来说已经足够好了。谢谢。 - 3nixios

1

你能否将b.call改为接收对a的引用?这样b.call就可以自己调用a.call

struct A {
    void call() {
        // do stuff
    }
};

struct B {
    void call(A & a) {
        a.call();
        // do stuff
    }
};

这样可以确保在执行 b.call 的其余部分之前,始终会先调用 a.call


+1 是的,保留依赖关系是不错的选择,但我更喜欢使用“友元类”来实现清理。 - 3nixios
@3nixios:它们更加简洁,但是根据你陈述的问题,它们并不能完全解决它。任何朋友的方法都可以调用该方法,因此仍然存在以错误的顺序调用的可能性。 - Björn Pollex
@Space_C0wb0y 这是真的,但对于我的特定用途,目前这已经足够好了。你的答案更具全球适用性,这就是为什么我还是点了赞的原因。 - 3nixios

0

使用一个标志如何?

a.call()
{
    // ...
    flag = 1;
    b.call();
    flag = 0;
}

b.call()
{
    if (flag == 0)
        return;

    // ...
}

这将需要两个类之间的共享标志,但我不太喜欢它。此外,友元类提供的编译时检查更加合适。 - 3nixios

0

如果你为某个平台编程(比如x86或x64),并且你知道调用约定(例如cdecl),那么你可以从堆栈中获取这些信息

假设你想要检查调用函数的对象,那么使用在调用成员函数之前推送到堆栈上的this指针:获取this指针并将其与所需的对象进行比较(this_pointer == a)。

如果你想要检查某个函数,从堆栈中获取调用者地址并检查是否与该函数匹配:caller_address == A::call。如果它是一个虚函数,则使用this指针来获取vtable

根据调用约定和将变量推入堆栈的顺序,你可能需要首先检查输入变量的大小,以便获得所需的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接