我有涉及不同类类型对象的应用程序。 目的是通过指针引用。 一个空指针表示该关联的对象不存在。 目前,调用代码很麻烦,因为每次它使用一个指向对象的指针,它测试空指针值,并采取了一些相应的动作为null。 由于采取在不存在的情况下,默认的操作取决于对象的类型,我宁愿它编码的类对象本身,而不是在调用程序。 这导致类似下面的结构:
class C
{ ...
void member_func() //non-virtual !
{ if (this) { do something with the object ... }
else { take some default action }
}
...
};
显然,成员函数不能是虚拟的,因为当对象不存在查找表不存在,和虚拟呼叫将会失败。 但是,这是合法的代码C ++非虚成员函数? 这似乎对我已经尝试过的编译器正常工作,但我担心可能的非便携性。 在标准我无法找到一个条款,要么明确允许或明确禁止这样的结构。
this
永远不会为空的成员函数,所以你执行检查是无用的。
正如评论指出由马修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,可以采取适当的行动。 如果“适当的行动”唯一地由持有类型决定的,你可以使用一个traits类来指定。
这样你的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;
}
};
不幸的是,我看不到的方式来做到这一点没有丢。 有没有办法拦截所有的方法名称的函数调用,否则我刚刚返回*this
从operator->
和做的工作在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将不会被允许。 所以,至少是我的猜测。