Вызов метода статического члена 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!".
Насколько я знаю, статические методы-члены не должны вызываться для экземпляра объекта.
- Я ошибся? Является ли этот код правильным со стандартной точки зрения?
- Если это правильно, то почему? Я не могу найти, почему это было бы разрешено, или, может быть, это помогает использовать метод "статический или нет" в шаблонах?
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
в сферу звонящего.