Chamada de método de membro estático C ++ na instância de class

Aqui está um pequeno programa de teste:

#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; } 

No VS2008 + SP1 (vc9) ele compila bem: o console exibe apenas “TEST IT!”.

Tanto quanto sei, methods de membros estáticos não devem ser chamados em objects instanciados.

  1. Estou errado? Este código está correto do ponto de vista padrão?
  2. Se está correto, por que isso? Não consigo descobrir por que isso seria permitido, ou talvez seja para ajudar a usar o método “estático ou não” nos modelos?

O padrão declara que não é necessário chamar o método por meio de uma instância, isso não significa que você não possa fazê-lo. Existe até um exemplo onde é usado:

C ++ 03, 9,4 membros estáticos

Um membro estático da class X pode ser referido usando a expressão id-qualificada X :: s; não é necessário usar a syntax de access do membro da class (5.2.5) para se referir a um membro estático. Um membro estático pode ser referido usando a syntax de access de membro de class, nesse caso a expressão de object é avaliada.

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

Funções estáticas não precisam de um object instanciado para serem chamadas, então

 k.DoCrash(); 

se comporta exatamente da mesma

 Test::DoCrash(); 

usando o operador de resolução de escopo (: 🙂 para determinar a function estática dentro da class.

Observe que, em ambos os casos, o compilador não coloca this ponteiro na pilha, pois a function estática não precisa dele.

2) Se estiver correto, por que isso? Não consigo descobrir por que isso seria permitido, ou talvez seja para ajudar a usar o método “estático ou não” nos modelos?

É potencialmente útil em vários cenários:

  • [o método “estático ou não” em modelos “você sugere:] quando muitos tipos poderiam ter sido especificados para um modelo, e o modelo então deseja invocar o membro: os tipos que fornecem uma function estática podem ser chamados usando a mesma notação como uma function de membro – o primeiro pode ser mais eficiente (não this ponteiro para passar / vincular), enquanto o último permite despacho polimórfico ( virtual ) e uso de dados de membro

  • minimizando a manutenção de código

    • se uma function evolui da necessidade de dados específicos da instância para não precisar dela e, portanto, torna-se static para permitir o uso livre de instância e evitar o uso acidental de dados da instância, todos os pontos de uso do cliente existente não precisam ser atualizados laboriosamente

    • se o tipo mudou a invocação var.f() continua a usar a function do tipo var , enquanto que Type::f() pode precisar de correção manual

  • quando você tem uma expressão ou function chamada retornando um valor e deseja invocar a function static (potencialmente ou sempre), o . A notação pode impedir que você precise usar o decltype ou um modelo de suporte para obter access ao tipo, apenas para que você possa usar a notação:

  • Às vezes, o nome da variável é muito mais curto, mais conveniente ou nomeado de maneira mais auto-documentável.

methods estáticos podem ser chamados também usando um object da class, assim como isso pode ser feito em Java. No entanto, você não deveria fazer isso. Use o operador de escopo como Test::DoCrash(); Talvez você pense em namespaces:

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

que só pode ser chamado por Test::DoCrash(); de fora desse namespace se a function não for importada explicitamente usando uma using directive/declaration no escopo do chamador.