获取d中的调用对象或方法
有点像 有没有办法从d中的函数或方法中获取调用对象 例如:获取d中的调用对象或方法,d,D,有点像 有没有办法从d中的函数或方法中获取调用对象 例如: class Foo { public void bar() { auto ci = whoCalledMe(); // ci should be something that points me to baz.qux, _if_ baz.qux made the call } } class Baz { void qux() { auto foo
class Foo
{
public void bar()
{
auto ci = whoCalledMe();
// ci should be something that points me to baz.qux, _if_ baz.qux made the call
}
}
class Baz
{
void qux()
{
auto foo = new Foo();
foo.bar();
}
}
问题:
whoCalledMe
这样的东西是否存在?如果是,它叫什么debug\u backtrace
无法直接获取有关“来电者”的信息。您可能有幸从调用堆栈中获得地址,但这是一个低级操作,取决于您的程序是否使用堆栈帧编译。在获得地址后,理论上可以将其转换为函数名和行号,前提是程序的二进制文件可以使用调试符号,但(同样)这是高度平台特定的,并且取决于用于编译程序的工具链 作为替代方案,您可能会发现以下内容很有帮助:
void callee(string file=__FILE__, int line=__LINE__, string func=__FUNCTION__)()
{
writefln("I was called by %s, which is in %s at line %d!", func, file, line);
}
void caller()
{
// Thanks to IFTI, we can call the function as usual.
callee();
}
但请注意,您不能对非final类方法使用此技巧,因为对函数的每次调用都将生成一个新的模板实例(并且编译器需要事先知道类的所有虚拟方法的地址)。要扩展什么,由于可以使用\uuuu function\uuuu
获取函数的完全限定名,因此也可以使用mixin将函数作为符号获取:
import std.stdio;
import std.typetuple;
void callee(string file=__FILE__, int line=__LINE__, string func=__FUNCTION__)()
{
alias callerFunc = TypeTuple!(mixin(func))[0];
static assert(&caller == &callerFunc);
callerFunc(); // will eventually overflow the stack
}
void caller()
{
callee();
}
void main()
{
caller();
}
堆栈将在此溢出,因为这两个函数最终会无限期地递归调用对方。查找调用者是调试器所做的事情,通常需要在编译程序时打开符号调试信息开关。阅读调试信息以了解这一点是高度依赖于系统的,而且非常先进
异常解除机制也会找到调用者,但这些表不是为不需要它们的函数生成的,并且这些表不包含函数的名称。当调用也可以从
main
@ratchetfreak进行时,这有点困难:我没有领会你评论的要点?请记住,代码是用来解释一般情况的,而不是用来约束问题的。我认为在任何编译语言中都不可能实现您想要的。关于问题2:在编译时,一个函数可以有多个调用者,你可以得到所有可能调用者的列表(我认为这在D中现在是不可能的)。@MichalMinich:只要我调用的函数是一个模板,我就可以在编译时编译一个函数的专用版本。我发现,甚至使用过,文件和行,但还不知道函数。这些“神奇常数”还有更多吗?\uuuuuu函数\uuuuuu
最近发布。这个关键字家族的列表是。嗯,如果你多次使用它,会增加大量代码膨胀。。。这不是一个理想的解决方案,要避免“代码膨胀”,使模板成为存根,只需将编译时变量作为运行时变量传递给非模板函数。使用-inline
,就好像第二个函数是用调用站点上指定的文件和行直接调用的一样。通常,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。否则,每次调用函数时都会再次实例化该函数。通常,将它们作为默认参数添加到函数签名的末尾就可以了。建议任何人使用它们作为模板参数几乎总是不好的建议。另外,当您将它们用作函数参数时,您不需要模板,它可以与虚拟函数一起工作。如果我请求一个功能\uuuuu CLASS\uuuuu
,就像已经有\uuuu FILE\uuuuuuu
、\uuu LINE\uuuuuuuuu
和\uuuuuu函数
?当我们这样做的时候,我可能还需要\uuuu模块
。顺便说一句,我非常愿意“做必要的文书工作”。\uu模块
已经实现。您可以从\uuuu函数\uuuu
中提取该类,因为它是完全限定的。@CyberShadow我可以,但为什么需要混乱呢?它似乎太适合其他魔术常数不存在于我。事实上,它的缺失可以被视为有点令人惊讶。必须已经阅读了\uuuuu模块
,因为它不在代码示例中。我的错。每一种语言的增加都有它的分量。此外,您希望它如何处理嵌套类?