Вызов метода статического члена C++ для экземпляра класса

Вот небольшая тестовая программа:

#include <iostream>

class Test
{
public:
    static void DoCrash(){ std::cout<< "TEST IT!"<< std::endl; }
};

int main()
{
    Test k;
    k.DoCrash(); // calling a static method like a member method...

    std::system("pause");

    return 0;
}

На VS2008 + SP1 (vc9) он компилируется нормально: консоль просто отображает "TEST IT!".

Насколько я знаю, статические методы-члены не должны вызываться для экземпляра объекта.

  1. Я ошибся? Является ли этот код правильным со стандартной точки зрения?
  2. Если это правильно, то почему? Я не могу найти, почему это было бы разрешено, или, может быть, это помогает использовать метод "статический или нет" в шаблонах?

4 ответа

Решение

Стандарт гласит, что нет необходимости вызывать метод через экземпляр, это не значит, что вы не можете это сделать. Есть даже пример, где он используется:

C++ 03, 9.4 статические члены

На статический член класса X можно ссылаться с помощью выражения квалифицированного идентификатора X::s; нет необходимости использовать синтаксис доступа к членам класса (5.2.5) для ссылки на статический член. К статическому члену можно обращаться с использованием синтаксиса доступа к члену класса, и в этом случае оценивается выражение объекта.

class process {
public:
   static void reschedule();
};

process& g();

void f()
{
   process::reschedule(); // OK: no object necessary             
   g().reschedule(); // g() is called
}

Статическим функциям не нужен экземпляр объекта для вызова, поэтому

k.DoCrash();

ведет себя точно так же, как

Test::DoCrash();

использование оператора разрешения контекста (::) для определения статической функции внутри класса.

Обратите внимание, что в обоих случаях компилятор не помещает this указатель в стеке, так как статическая функция не нуждается в этом.

2) Если это правильно, то почему? Я не могу найти, почему это было бы разрешено, или, может быть, это помогает использовать метод "статический или нет" в шаблонах?

Это потенциально полезно в нескольких сценариях:

  • [метод "статический или нет" в шаблонах ", который вы предлагаете:] когда в шаблоне может быть указано много типов, и шаблон затем хочет вызвать член: типы, предоставляющие статическую функцию, могут вызываться с использованием одной и той же записи как функция-член - первый может быть более эффективным (нет this указатель на pass/bind), в то время как последний допускает полиморфизм (virtual) отправка и использование данных участника

  • сведение к минимуму обслуживания кода

    • если функция эволюционирует от потребности в специфичных для экземпляра данных, чтобы не нуждаться в них - и поэтому делается static для легкого использования без экземпляров и предотвращения случайного использования данных экземпляров - все точки существующего использования клиента не должны быть тщательно обновлены

    • если тип изменился var.f() вызов продолжает использовать var функция типа, тогда как Type::f() может потребоваться ручная коррекция

  • когда у вас есть выражение или вызов функции, возвращающей значение, и вы хотите вызвать (потенциально или всегда) static функция, . нотация может помешать вам использовать decltype или вспомогательный шаблон, чтобы получить доступ к типу, просто чтобы вы могли использовать :: обозначение

  • иногда имя переменной намного короче, удобнее или названо более самодокументированным способом

Статические методы могут быть вызваны также с использованием объекта класса, так же как это может быть сделано в Java. Тем не менее, вы не должны этого делать. Используйте оператор области как Test::DoCrash(); Может быть, вы думаете о пространствах имен:

namespace Test {
    void DoCrash() {
        std::cout << "Crashed!!" << std::endl;
    }
};

который может быть вызван только Test::DoCrash(); извне этого пространства имен, если функция не импортирована явно с использованием using directive/declaration в сферу звонящего.

Другие вопросы по тегам