С++ Метод статического члена вызывает экземпляр класса
Вот небольшая тестовая программа:
#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!".
Насколько я знаю, статические методы-члены не должны вызываться на объекте instanced.
- Я не прав? Правильно ли этот код со стандартной точки зрения?
- Если это правильно, почему? Я не могу найти, почему это допустимо, или, может быть, это поможет использовать метод "статический или нет" в шаблонах?
Ответы
Ответ 1
В стандарте указано, что нет необходимости вызывать метод через экземпляр, что не означает, что вы не можете этого сделать. Существует даже пример, где он используется:
С++ 03, 9.4 статические элементы
Статический член класса X может быть отнесен к использованию expression-id-выражение 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
}
Ответ 2
Статические функции не нуждаются в подстроенном объекте для вызова, поэтому
k.DoCrash();
ведет себя точно так же, как
Test::DoCrash();
с помощью оператора разрешения области (::) для определения статической функции внутри класса.
Обратите внимание, что в обоих случаях компилятор не ставит указатель this
в стек, так как статическая функция не нуждается в нем.
Ответ 3
2) Если это правильно, почему? Я не могу найти, почему это разрешено, или, может быть, это поможет использовать метод "статический или нет" в шаблонах?
Это потенциально полезно в нескольких сценариях:
-
[ "статический или нет" метод в шаблонах "вы предлагаете:] когда многие типы могли быть указаны в шаблоне, а затем шаблон хочет вызвать этот элемент: типы, предоставляющие статическую функцию, могут вызывается с использованием той же нотации, что и функция-член, - первая может быть более эффективной (нет this
указатель на передачу/привязку), в то время как последняя допускает полиморфную (virtual
) отправку и использование данных элемента
-
минимизация обслуживания кода
-
если функция возникает из-за необходимости получения данных, специфичных для экземпляра, и не нуждается в ней, и поэтому она делает static
, чтобы обеспечить удобство использования без экземпляра и предотвратить случайное использование данных экземпляра - все точки использования существующего клиента не нуждайтесь в том, чтобы быть обновленно.
-
если тип изменил вызов var.f()
, продолжает использовать функцию типа var
, тогда как Type::f()
может потребоваться ручная коррекция
-
когда у вас есть вызов выражения или функции, возвращающий значение, и вы хотите вызвать функцию (потенциально или всегда) static
, нотация .
может помешать вам использовать decltype
или поддерживающий шаблон чтобы получить доступ к типу, так что вы можете использовать нотацию ::
-
иногда имя переменной намного короче, удобнее или названо более самодокументированным способом.
Ответ 4
статические методы можно вызвать также с помощью объекта класса, как это можно сделать на Java. Тем не менее, вы не должны этого делать. Используйте оператор области видимости как Test::DoCrash();
Возможно, вы думаете о пространствах имен:
namespace Test {
void DoCrash() {
std::cout << "Crashed!!" << std::endl;
}
};
который может быть вызван только Test::DoCrash();
извне этого пространства имен, если функция не импортируется явно с помощью using directive/declaration
в область действия вызывающего.