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

sha*_*oth 57 c++ pointers static-members undefined-behavior dereference

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

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

((Class*)0)->Method();
Run Code Online (Sandbox Code Playgroud)

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

Class::Method();
Run Code Online (Sandbox Code Playgroud)

而后者也没关系.

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

eca*_*mur 67

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

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

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

((X*)0)->f();
Run Code Online (Sandbox Code Playgroud)

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

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

成员函数的注释static确实是一个难题,如Cheers和hth.- 阿尔夫观察到了; Cfront 1.0会拒绝该代码:

error:  member Method() cannot be static
Run Code Online (Sandbox Code Playgroud)

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

  • +1我爱这个闪回到90年代 (6认同)
  • @ Cheersandhth.-Alf可能客户端(函数调用)代码比较粗糙,库(类定义)在引入后用`static`更新.或者,它是两个程序员的产物,其中一个是不合时宜的. (4认同)
  • ** - 1**一般很好的答案!但是,两次错误的结论"你的代码是用C++ 1.x编写的,或者是在向语言添加静态成员函数时不知道的人." 由于代码使用`static`关键字,因此这些可能性都不是真的.如果没有`static`成员函数,代码将无法在C++版本中编译.而使用`static`的程序员也不会意识不到它.对不起我早就读不到了. (3认同)