为什么代码会通过空指针显式调用静态方法?

时间:2014-09-08 07:25:44

标签: c++ pointers static-members undefined-behavior dereference

我在几个旧项目中看到过这样的代码:

class Class {
    static void Method() {}
};

((Class*)0)->Method();

此代码包含未定义的行为,因为它包括取消引用空指针(无论之后发生什么)。它真的没有任何意义 - 演员是在那里将类型名称提供给编译器,而编写上述代码的人可能会写这个:

Class::Method();

后者可以。

为什么有人会编写前代码?它是一个已知的成语来自一些美好的旧时代或什么?

1 个答案:

答案 0 :(得分:67)

静态成员函数于1989年在AT& T C ++语言系统(预标准化)的Release 2.0中添加到C ++中。在此之前,static关键字不能用于声明静态成员函数,因此代码作者使用了变通方法,主要是您观察到的间接空指针的方法。

在AT& T C ++语言系统的Selected Readings附带版本2.0中,在第1-22节中,Stroustrup写道:

  

还观察到了不可移植的代码,例如:

((X*)0)->f();
     

用于模拟静态成员函数。这个技巧是一个定时炸弹,因为迟早有人会以这种方式f()使用virtual并且调用将会失败,因为地址为零时没有X个对象。即使f()不是虚拟的,在某些动态链接实现下,这样的调用也会失败。

您的代码是在Cfront 1.0下编译的,或者是在向该语言添加静态成员函数时不知道的人编写的。

使用static的成员函数的注释确实是一个难题,如干杯和hth。 - Alf 观察到了; Cfront 1.0会拒绝该代码:

error:  member Method() cannot be static

所以它最初不可能存在。我认为 Potatoswatter 最有可能是正确的;稍后添加static来记录并强制执行Method的静态方法属性,一旦C ++ 2.0编译器可以保证可用,但不更新调用代码。要确认这一点,您需要采访原始程序员或至少检查源控制历史记录(如果存在)。