Pergunta

Como você cria uma classe estática em C++?Eu deveria ser capaz de fazer algo como:

cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;

Supondo que eu criei BitParser de classe.O que seria o BitParser definição de classe se parece?

Foi útil?

Solução

Se você está procurando uma forma de aplicar a "estática" palavra-chave para uma classe, como você pode em C#, por exemplo, então você não será capaz sem usar C++Gerido.

Mas a aparência do seu exemplo, você precisa apenas criar um método estático público no seu BitParser objeto.Assim:

BitParser.h

class BitParser
{
 public:
  static bool getBitAt(int buffer, int bitIndex);

  // ...lots of great stuff

 private:
  // Disallow creating an instance of this object
  BitParser() {}
};

BitParser.cpp

bool BitParser::getBitAt(int buffer, int bitIndex)
{
  bool isBitSet = false;
  // .. determine if bit is set
  return isBitSet;
}

Você pode usar esse código para chamar o método, da mesma forma como o seu exemplo de código.

Espero que ajude!Cheers.

Outras dicas

Considere Matt Preço da solução.

  1. Em C++, uma "classe estática" não tem nenhum significado.A coisa mais próxima é uma classe com apenas métodos estáticos e de seus membros.
  2. Usando métodos estáticos só vai limitá-lo.

O que você quer é, expressa em C++ semântica, para colocar a sua função (por ele é uma função) em um espaço de nomes.

Editar 2011-11-11

Não há nenhuma "classe estática" em C++.O próximo conceito seria uma classe com apenas métodos estáticos.Por exemplo:

// header
class MyClass
{
   public :
      static void myMethod() ;
} ;

// source
void MyClass::myMethod()
{
   // etc.
}

Mas você deve se lembrar que "classes estáticas" são hacks em Java-como uma espécie de línguas (por exemplo,C#) que são incapazes de ter a não-membro, funções, de modo que eles têm, em vez de movê-los dentro de classes como métodos estáticos.

Em C++, o que você realmente deseja é uma não-função de membro que você vai declarar em um espaço de nomes:

// header
namespace MyNamespace
{
   void myMethod() ;
}

// source
namespace MyNamespace
{
   void myMethod()
   {
      // etc.
   }
}

Por que isso?

Em C++, o namespace é mais poderoso do que para as turmas de Java "método estático" padrão, porque:

  • métodos estáticos têm acesso a aulas particulares símbolos
  • privada métodos estáticos são ainda visíveis (se inacessível para todos, que as violações um pouco o encapsulamento
  • métodos estáticos não podem ser frente-declarou
  • métodos estáticos não podem ser sobrecarregadas pela classe de usuário, sem necessidade de modificar o cabeçalho da biblioteca
  • não há nada que possa ser feito por um método estático que não pode ser feito melhor do que um (possivelmente amigo) função de membro não no mesmo espaço de nomes
  • espaços de nomes têm a sua própria semântica (eles podem ser combinados, eles podem ser anônimos, etc.)
  • etc.

Conclusão:Não copie/cole Java/C#'s padrão em C++.Em Java/C# o padrão é obrigatório.Mas em C++, é mau estilo.

Editar 2010-06-10

Havia um argumento a favor para o método estático, porque, às vezes, é necessário usar um estática variável de membro privado.

Eu discordo um pouco, como mostra abaixo:

A "Estática de membro privado" solução

// HPP

class Foo
{
   public :
      void barA() ;
   private :
      void barB() ;
      static std::string myGlobal ;
} ;

Primeiro, myGlobal é chamado myGlobal porque ele ainda é uma global variável privada.Um olhar para o CPP fonte de esclarecer que:

// CPP
std::string Foo::myGlobal ; // You MUST declare it in a CPP

void Foo::barA()
{
   // I can access Foo::myGlobal
}

void Foo::barB()
{
   // I can access Foo::myGlobal, too
}

void barC()
{
   // I CAN'T access Foo::myGlobal !!!
}

À primeira vista, o fato de a função livre barC não pode acessar o Foo::myGlobal parece uma boa coisa a partir de um encapsulamento ponto de vista...É legal porque alguém olhar para a UHE de não ser capaz de (a menos que recorrer a sabotagem) para acesso Foo::myGlobal.

Mas se você olhar de perto, você vai descobrir que ele é um colossal erro:Não só a sua variável privada deve ser declarado na UHE (e, portanto, visível para todo o mundo, apesar de ser privado), mas você deve declarar no mesmo UHE todos (como em TODAS as funções que serão autorizados a acessá-lo !!!

Então, utilizando um membro estático privado é como andar para fora nua, com a lista de seus amantes tatuado em sua pele :Ninguém está autorizado a tocar, mas todo mundo é capaz de espreitar.E o bonus:Todos podem ter os nomes das pessoas autorizadas a jogar com o seu privies.

private de fato...:-D

O "Anônimo namespaces" solução

Anônimo namespaces terá a vantagem de fazer as coisas privado realmente privada.

Primeiro, a UHE de cabeçalho

// HPP

namespace Foo
{
   void barA() ;
}

Só para ter certeza de que você comentou:Não há inútil declaração de barB nem myGlobal.O que significa que ninguém a leitura do cabeçalho sabe o que está escondido atrás de barA.

Em seguida, o CPP:

// CPP
namespace Foo
{
   namespace
   {
      std::string myGlobal ;

      void Foo::barB()
      {
         // I can access Foo::myGlobal
      }
   }

   void barA()
   {
      // I can access myGlobal, too
   }
}

void barC()
{
   // I STILL CAN'T access myGlobal !!!
}

Como você pode ver, como a chamada "classe estática" declaração, fooA e fooB ainda são capazes de acessar myGlobal.Mas ninguém mais pode.E ninguém mais fora isso CPP sabe fooB e myGlobal existe mesmo!

Ao contrário da "classe estática" walking on the nude com seu livro de endereços tatuado em sua pele o "anônimo" espaço de nomes é totalmente vestido, que parece muito melhor encapsulado AFAIK.

O que realmente importa?

A menos que o usuários do seu código são sabotadores (eu vou deixar você, como um exercício, como encontrar um pode aceder à parte privada de uma classe pública usando uma sacanagem de comportamento indefinido hack...), o que private é private, mesmo se ele estiver visível no private seção de uma classe declarada no cabeçalho.

Ainda assim, se você precisar adicionar outra "função particular" com acesso privativo de membro, você ainda deve declará-lo de todo o mundo, modificando o cabeçalho, o que é um paradoxo, tanto quanto eu estou preocupado: Se eu alterar a implementação de meu código (CPP parte) e, em seguida, a interface (UHE parte) NÃO devem mudar. Citando Leonidas :"Este é o ENCAPSULAMENTO!"

Editar 2014-09-20

Quando são classes de métodos estáticos são, na verdade, melhor do que espaços de não-funções de membro?

Quando você precisa agrupar funções e alimentar o grupo para um modelo:

namespace alpha
{
   void foo() ;
   void bar() ;
}

struct Beta
{
   static void foo() ;
   static void bar() ;
};

template <typename T>
struct Gamma
{
   void foobar()
   {
      T::foo() ;
      T::bar() ;
   }
};

Gamma<alpha> ga ; // compilation error
Gamma<Beta> gb ;  // ok
gb.foobar() ;     // ok !!!

Porque, se uma classe pode ser um parâmetro do modelo, uma namespaces não é possível.

Você também pode criar uma função livre em um espaço de nomes:

Em BitParser.h

namespace BitParser
{
    bool getBitAt(int buffer, int bitIndex);
}

No BitParser.cpp

namespace BitParser
{
    bool getBitAt(int buffer, int bitIndex)
    {
        //get the bit :)
    }
}

Em geral, esta seria a melhor maneira para escrever o código.Quando não há necessidade de um objeto não usar uma classe.

Se você está procurando uma forma de aplicar a "estática" palavra-chave para uma classe, como você pode em C#, por exemplo,

classes estáticas são apenas o compilador a mão à você e que você parar de gravar os métodos de instância/variáveis.

Se você acabou de escrever uma classe normal, sem qualquer métodos de instância/variáveis, é a mesma coisa, e isso é o que você poderia fazer em C++

Em C++ você deseja criar uma função estática de uma classe (não uma classe estática).

class BitParser {
public:
  ...
  static ... getBitAt(...) {
  }
};

Em seguida, você deve ser capaz de chamar a função usando BitParser::getBitAt() sem instanciar um objeto que eu presumo que é o resultado desejado.

Posso escrever algo como static class?

Nenhum, de acordo com o C++11 N3337 rascunho padrão Anexo C 7.1.1:

Alteração:Em C ++, a estática ou externo especificadores só podem ser aplicadas a nomes de objetos ou funções.Usando estes especificadores com declarações de tipo é ilegal em C ++.Em C, estes especificadores são ignorados quando usado no tipo de declarações.Exemplo:

static struct S {    // valid C, invalid in C++
  int i;
};

Justificativa:Especificadores de classe de armazenamento não têm qualquer significado quando associada a um tipo.Em C ++, classe os membros podem ser declaradas com o especificador de classe de armazenamento estático.Permitindo o armazenamento especificadores de classe de tipo declarações podem tornar o código confuso para os usuários.

E como struct, class é também uma declaração de tipo.

O mesmo pode ser deduzido pelo andar da árvore de sintaxe no Anexo A.

É interessante notar que static struct foi legal em C, mas não teve efeito: Por que e quando usar estruturas estáticas na programação de C?

E 'pode' ter uma classe estática em C++, como mencionado antes, uma classe estática é aquela que não tem quaisquer objetos de que ele é instanciado.Em C++, isto pode ser obtido por declarar o construtor/destruidor como privado.Resultado final é o mesmo.

Em C++ Gerenciado, classe estática sintaxe é:-

public ref class BitParser abstract sealed
{
    public:
        static bool GetBitAt(...)
        {
            ...
        }
}

...melhor tarde do que nunca...

Este é semelhante ao C#'s forma de fazer isso em C++

No C# do arquivo.cs você pode ter private var dentro de uma função pública.Quando em outro arquivo você pode usá-lo ligando para o espaço de nomes com a função, como em:

MyNamespace.Function(blah);

Veja como imp mesmo em C++:

SharedModule.h

class TheDataToBeHidden
{
  public:
    static int _var1;
    static int _var2;
};

namespace SharedData
{
  void SetError(const char *Message, const char *Title);
  void DisplayError(void);
}

SharedModule.cpp

//Init the data (Link error if not done)
int TheDataToBeHidden::_var1 = 0;
int TheDataToBeHidden::_var2 = 0;


//Implement the namespace
namespace SharedData
{
  void SetError(const char *Message, const char *Title)
  {
    //blah using TheDataToBeHidden::_var1, etc
  }

  void DisplayError(void)
  {
    //blah
  }
}

OtherFile.h

#include "SharedModule.h"

OtherFile.cpp

//Call the functions using the hidden variables
SharedData::SetError("Hello", "World");
SharedData::DisplayError();

Ao contrário de outros gerenciado linguagem de programação, a "classe estática" não tem NENHUM significado em C++.Você pode fazer uso da função de membro estático.

Como já foi observado aqui, a melhor maneira de conseguir isso em C++, pode estar a utilizar espaços de nomes.Mas desde que ninguém tenha mencionado a final palavra-chave aqui, estou postando o que um equivalente direto do static class a partir do C# ficaria em C++11 ou posterior:

class BitParser final
{
public:
  BitParser() = delete;

  static bool GetBitAt(int buffer, int pos);
};

bool BitParser::GetBitAt(int buffer, int pos)
{
  // your code
}

Um caso onde a espaços de nomes pode não ser tão útil para a realização dos "classes estáticas" é ao usar essas classes para alcançar a composição através de herança.Espaços de nomes não podem ser amigos de classes e, portanto, não pode acessar membros privados de uma classe.

class Class {
 public:
  void foo() { Static::bar(*this); }    

 private:
  int member{0};
  friend class Static;
};    

class Static {
 public:
  template <typename T>
  static void bar(T& t) {
    t.member = 1;
  }
};
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top