Почему код явно вызывал статический метод с помощью нулевого указателя?

Я видел такой код в нескольких старых проектах:

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

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

Этот код содержит поведение undefined, поскольку он включает разыменование нулевого указателя (независимо от того, что происходит потом). Это действительно не имеет смысла - приведение должно содержать имя типа для компилятора, и тот, кто написал код выше, мог бы написать это вместо:

Class::Method();

и последнее будет в порядке.

Зачем кому-то писать прежний код? Это известная идиома из старых добрых дней или что?

Ответ 1

Статические функции-члены были добавлены в С++ в 1989 году в Release 2.0 системы языка AT & T С++ (предварительная стандартизация). До этого ключевое слово static не могло использоваться для объявления статических функций-членов, поэтому авторы кода использовали обходные пути, в основном тот, который вы наблюдали за косвенностью нулевого указателя.

В Избранные чтения, сопровождающие версию 2.0 системы языка AT & T С++, в разделе 1-22, Stroustrup пишет:

Было также отмечено, что непереносимый код, например:

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

использовался для моделирования статических функций-членов. Этот трюк - это бомба замедленного действия, потому что рано или поздно кто-то сделает f(), который используется таким образом virtual, и вызов будет терпеть неудачу, потому что нет объекта X при нулевом адресе. Даже там, где f() не является виртуальным, такие вызовы будут терпеть неудачу при некоторых реализациях динамической компоновки.

Ваш код был написан для компиляции под Cfront 1.0 или кем-то, кто не знал о добавлении статических функций-членов к языку.

Аннотация функции-члена с static действительно является загадкой, как Cheers и hth. - заметил Альф; Cfront 1.0 отклонил бы этот код с помощью:

error:  member Method() cannot be static

поэтому он не мог быть там изначально. Я думаю, что Potatoswatter, скорее всего, правильный; static был добавлен позднее, чтобы документировать и применять атрибут статического метода Method, как только может быть гарантирован доступ к компилятору С++ 2.0, но без обновления кода вызова. Чтобы подтвердить это, вам нужно взять интервью у первоначального программиста или изучить историю управления версиями (если таковая существует).