c++在成员函数中测试this指针是否合法?
Is it legal C++ to test the this-pointer in a member function?
我有一个涉及不同类类型对象的应用程序。对象由指针引用。空指针表示关联对象不存在。目前调用代码很麻烦,因为每次使用指向对象的指针时,它都会测试指针值是否为空,并在为空时采取一些适当的操作。因为在不存在的情况下采取的默认操作取决于对象的类型,所以我更愿意将其编码在对象本身的类中,而不是在调用程序中。这将导致如下结构:
class C
{ ...
void member_func() //non-virtual !
{ if (this) { do something with the object ... }
else { take some default action }
}
...
};
显然成员函数不能是虚函数,因为当对象不存在时查找表不存在,虚函数调用将失败。但是对于非虚成员函数,这段代码合法吗?对于我尝试过的编译器,它似乎可以正确地工作,但我担心可能的不可移植性。在标准中,我找不到一个明确允许或明确禁止这种结构的条款。
this
在成员函数中永远不会为null,因此您执行的检查是无用的。
正如Matthieu M.在注释中指出的,如果你在代码中做了这样的事情:
C* c = 0;
c->member();
这会导致未定义行为,这是不好的。
如前所述,this
永远不能是空指针。如果是,那么您已经调用了未定义的行为。相反,您可以创建一组重载函数,如下所示:
void DoTheThing(C* cp)
{
if (cp)
cp->member_func();
else
{
// take some default action
}
}
void DoTheThing(B* bp)
{
if (bp)
bp->some_other_member_func();
else
{
// take some default action
}
}
如果你想调用的函数在每个类中都有相同的名称,那么你可以在每个类中创建一个静态函数,执行该类的默认操作(所有函数都具有相同的名称),并创建一个模板:
template<typname T>
void DoTheThing(T* tp)
{
if (tp)
tp->member_func();
else
T::default_action()
}
标准而言,代码是不合法的,但是它在实践中被使用(是坏的实践)。
实际上,IIRC MFC在内部使用这些检查
检查 this == NULL
是否无问题。通过NULL对象指针调用方法是。
如果你想把检查放在某个地方,你可以把它放在一个智能指针类中,如果持有的指针为NULL,它可以采取适当的行动。如果"适当的操作"是由持有的类型唯一决定的,你可以使用trait类来指定它。
这样你的NULL检查和他们的逻辑是保持在一起的,而不是混合到调用者或方法代码。
// specialize this to provide behaviour per held type
template <typename T> struct MaybeNullDefaultAction {
void null_call() { throw std::runtime_error("call through NULL pointer"); }
}
template <typename T> class MaybeNull: MaybeNullDefaultAction<T> {
T *ptr;
public:
explicit MaybeNull(T *p) : ptr(p) {}
T* operator-> () {
if (!ptr)
null_call();
// null_call should throw to avoid returning NULL here
return ptr;
}
};
不幸的是,我看不到没有抛出的方法。没有办法拦截所有方法名称的函数调用,否则我就从operator->
返回*this
,并在operator()
中完成工作。
我认为这是不允许的。你要求参考标准。我相信首先感兴趣的是9.3.1非静态成员函数,1.:
非静态成员函数可以为其类的对象调用类型,或从其类派生的类(第10条)的对象类型,使用类成员访问语法(5.2.5,13.3.1.1)。其次,让我们看一下5.2.5类成员访问,2.:
表达式E1->E2被转换成等价形式(*(E1))。E2;5.2.5的剩余部分将只处理第一个选项(点)。
所以如果E1是nullptr
, *E1将不被允许。
- std::vector::迭代器是否可以合法地作为指针
- 是否可以将llvm::FunctionType转换为C/C++原始函数指针
- 返回指向对象的指针的函数调用是否为 prvalue?
- 对象初始化中是否允许指向此成员的指针?
- 新分配指向函数的指针是否合法?
- 在函数结束后使用指向变量的指针是否安全?
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 在对象指针上调用 Delete 是否会递归删除其动态分配的成员
- 如果整数与指针大小相同,则重新解释将整数转换为指针双射是否具有双射作用?
- 是否可以使用函数指针调用虚拟析构函数?
- std::less是否应该允许在编译时比较不相关的指针?
- 是否允许编译器省略对指针的 &* 运算符的组合调用?
- 将相同共享指针的副本存储在不同的向量中是否是一种好的做法?
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 检查输入 std::array 指针数据是否等于某个常量数组
- 成员访问是否在空指针上定义C++?
- 如果只有 std::auto_ptr 可用,我是否仍应该使用智能指针?
- 是否可以使用指针访问变量以避免直接编辑变量?
- 是否可以仅通过将分配的指针地址存储在C++中来分析内存?
- "this"指针的值在对象的生存期内是否恒定?