当a)在c自由函数中或b)在类的成员函数中时:
我如何将a)nullptr分别B)this 传递给一个对两者都有效的通用宏?
我知道,我们不应该使用宏--但是我有遗留代码。也许以后宏可以被替换。但是我认为问题仍然是一样的:如何检测a)在c的自由函数中或者B)在类的成员函数中,并且因此使用a)nullptr或者b)this ptr进行处理?
#include <iostream>
#define MYMACRO \
{ \
if (1) { /* what to use here? */ \
std::cout << "MYMACRO used in a member function of class this ptr = " << "" /* print this here */ << std::endl; \
} \
else { \
std::cout << "MYMACRO used in a free function" << std::endl; \
} \
}
struct MyStruct
{
MyStruct() = default;
~MyStruct() = default;
void SomeMemberFunction(void)
{
MYMACRO;
}
};
void SomeFreeFunction(void)
{
MYMACRO;
}
int main(int, char**)
{
MyStruct myStruct;
myStruct.SomeMemberFunction();
SomeFreeFunction();
return 0;
}
例如,应在MYMACRO内检测到空指针或 * 此 * 指针。
附录1
下面的一些评论问的目的-在混凝土从@Nicol Bolas。
想象一下MYMACRO已经有一些功能,但是应该扩展以额外提供一个新的日志函数(可选)。当MYMACRO用于成员函数时,类名和这个ptr值将被记录用于跟踪和关联。只是作为一个例子。那么MYMACRO需要知道是否在类成员函数的上下文中使用(即,是否有一些 * 这个 * ptr可用)。
一般性谈话:是关于“反思”
4条答案
按热度按时间klsxnrf11#
如果您不介意为需要调用宏的任何类继承接口类,则可以采用以下方法:
注意,我将使用“MYMACRO”作为对执行该工作的程序部分的引用。* 它显然不是宏!* 相反,它只是一个函数,将使用NULL指针调用
DoSomething
。为了在类中重载此行为,必须定义一个接口:
然后,任何需要调用它的类都应该继承这个接口,当该类的方法调用
MYMACRO
时,它将使用SomethingDoer::MYMACRO
而不是另一个函数。如果你的宏还做了其他更方便使用宏的事情,那也没关系,你仍然可以用宏来实现,但是让与“this”相关的事情使用我描述过的机制。
如果您确实需要
this
的类型是正确的,那么可以做一个小的调整:flvlnr442#
对于独立函数来说,没有
this
,所以这部分问题没有意义。如果你的意思是如何检查局部变量x
是否有效,那就没有意义了。它总是有效的,并且在它的方法中,这不会是nullptr,除非你的代码做了一些可怕的事情(例如,不知何故从其他线程中断了堆栈)。宏定义只是简单地替换代码,因此如果您可以编写
你可以写
宏展开发生在编译之前,预处理器不分析你的代码,所以你不能改变宏的内容。也就是说,它必须发生在代码中。
一种“肮脏”的方法是定义一些全局函数,在每个对象中都有局部对应函数。在这种情况下,任何不包含该定义的对象方法都将表现为没有
this
。它可以通过继承来完成,就像paddy在他的答案中所展示的,或者类体中的另一个宏:
this
是否为nullptr
是一种偏执和无用的努力 *。您可以尝试仅用于调试目的,但您不能使用它来创建错误的“坚固”代码。事情是调用成员函数,并使用指向类类型示例的空指针是未定义的行为。编译器可以自由地假设未定义的行为没有发生。因此,在实践中,编译器可能会抛出那个if
,因为它在定义的行为边界内不可能是nullptr
。这不是假设,流行的编译器在优化打开时会这么做。检查对象的地址是否为
nullptr
必须在第一次在特定范围内使用它的成员之前进行,即在成员之外。在第一次使用或调用之后,检查没有意义。ukxgm1gy3#
对于c++17来说,这只完成了一半的工作
这种方法不起作用,因为__PRETTY_FUNCTION__也有一个嵌套在名称空间中的自由函数的':'。(参见下面Nicol Bolas的注解-谢谢Nicol!)
输出:
s4chpxco4#
我认为你最好做这样的事情:
当然,要使它工作,你需要在所有的基类中插入
DECLARE_GETTHIS();
,但是我没有看到任何其他的方法没有 * 一些 * 修改类。全局
get_this()
的声明可以放置在使用inline
说明符定义MYMACRO()
的同一标头中。此外,如果需要在旧版本中使用
if constexpr
,可以将constexpr
删除。