Вызов метода статического члена C ++ для экземпляра класса - PullRequest
36 голосов
/ 28 ноября 2008

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

#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 ]

60 голосов
/ 28 ноября 2008

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

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
}
11 голосов
/ 28 ноября 2008

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

k.DoCrash();

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

Test::DoCrash();

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

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

3 голосов
/ 30 июня 2015

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

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

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

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

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

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

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

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

2 голосов
/ 28 ноября 2008

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

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

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

...