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

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

#include  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. Я ошибаюсь? Правильно ли этот код со стандартной точки зрения?
  2. Если это правильно, почему? Я не могу найти, почему это разрешено, или, может быть, это поможет использовать метод «статический или нет» в шаблонах?

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

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

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

 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(); 

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Являются ли std :: векторные элементы гарантированными смежными?
  • Одномерный доступ к многомерному массиву: хорошо ли оно определено?
  • Порядок оценки в параметрах функции C ++
  • Использование Unicode в исходном коде на C ++
  • Есть ли способ доступа к базовому контейнеру контейнеров-контейнеров STL?
  • Подготовка к std :: iterator Будучи устаревшим
  • Нет определенного типа параметра функции по умолчанию для int? Я сошел с ума?
  • Предоставляет ли компилятор возможность переработать освобожденные переменные указателя?
  • Препроцессор C ++ идентичен препроцессору C?
  • Почему C ++ выводит отрицательные числа при использовании modulo?
  • Имеет ли printf ("% x", 1) неопределенное поведение?
  • Давайте будем гением компьютера.