Digamos que eu tenho, ou vou escrever, um conjunto de funções relacionadas. Digamos que eles estejam relacionados à matemática. Organizacionalmente, devo:
- Escreva essas funções e coloque-as no meu
MyMath
namespace e consulte-as viaMyMath::XYZ()
- Crie uma classe chamada
MyMath
e torne esses métodos estáticos e consulte a mesmaMyMath::XYZ()
Por que eu escolheria um sobre o outro como forma de organizar meu software?
c++
namespaces
static-methods
RobertL
fonte
fonte
Respostas:
Por padrão, use funções com espaço para nome.
As classes são para criar objetos, não para substituir espaços para nome.
No código Orientado a Objetos
Scott Meyers escreveu um item inteiro para seu livro Effective C ++ sobre este tópico, "Prefira funções de não-membro não-amigo a funções de membro". Encontrei uma referência on-line a esse princípio em um artigo da Herb Sutter:http://www.gotw.ca/gotw/084.htm
O importante é saber: No C ++, as funções no mesmo espaço de nomes que uma classe pertencem à interface dessa classe (porque o ADL pesquisará essas funções ao resolver chamadas de função).
Funções com espaço para nome, a menos que declarado "amigo", não têm acesso aos internos da classe, enquanto métodos estáticos.
Isso significa, por exemplo, que, ao manter sua classe, se você precisar alterar os componentes internos da sua classe, precisará procurar efeitos colaterais em todos os seus métodos, incluindo os estáticos.
Extensão I
Adicionando código à interface de uma classe.
Em C #, você pode adicionar métodos a uma classe, mesmo se você não tiver acesso a ela. Mas em C ++, isso é impossível.
Mas, ainda em C ++, você ainda pode adicionar uma função com espaço para nome, mesmo para uma classe que alguém escreveu para você.
Veja do outro lado, isso é importante ao projetar seu código, porque, ao colocar suas funções em um espaço para nome, você autorizará seus usuários a aumentar / concluir a interface da classe.
Extensão II
Um efeito colateral do ponto anterior, é impossível declarar métodos estáticos em vários cabeçalhos. Todo método deve ser declarado na mesma classe.
Para espaços para nome, funções do mesmo espaço para nome podem ser declaradas em vários cabeçalhos (a função de troca quase padrão é o melhor exemplo disso).
Extensão III
O frescor básico de um espaço para nome é que, em algum código, você pode evitar mencioná-lo, se você usar a palavra-chave "using":
E você pode até limitar a "poluição" a uma classe:
Esse "padrão" é obrigatório para o uso adequado do idioma de troca quase padrão.
E isso é impossível de se fazer com métodos estáticos nas classes.
Portanto, os namespaces do C ++ têm sua própria semântica.
Mas vai além, pois você pode combinar espaços para nome de maneira semelhante à herança.
Por exemplo, se você tiver um espaço para nome A com uma função AAA, um espaço para nome B com uma função BBB, poderá declarar um espaço para nome C e trazer AAA e BBB nesse espaço para nome com a palavra-chave using.
Conclusão
Os espaços para nome são para espaços para nome. As aulas são para aulas.
O C ++ foi projetado para que cada conceito seja diferente e seja usado de maneira diferente, em casos diferentes, como uma solução para diferentes problemas.
Não use classes quando precisar de espaços para nome.
E no seu caso, você precisa de espaços para nome.
fonte
Muitas pessoas discordam de mim, mas é assim que eu vejo:
Uma classe é essencialmente uma definição de um certo tipo de objeto. Os métodos estáticos devem definir operações intimamente ligadas a essa definição de objeto.
Se você deseja apenas ter um grupo de funções relacionadas não associadas a um objeto subjacente ou a definição de um tipo de objeto , então eu diria que vá apenas com um espaço para nome. Só para mim, conceitualmente, isso é muito mais sensato.
Por exemplo, no seu caso, pergunte a si mesmo: "O que é um MyMath?" Se
MyMath
não define um tipo de objeto, então eu diria: não faça disso uma classe.Mas, como eu disse, sei que há muitas pessoas que (até veementemente) discordam de mim sobre isso (em particular, desenvolvedores de Java e C #).
fonte
typedef
-los, usá-los como parâmetros do modelo, etc.Caso contrário, use funções com espaço para nome.
Em resposta aos comentários: sim, métodos estáticos e dados estáticos tendem a ser superutilizados. Por isso, ofereci apenas dois cenários relacionados , onde acho que podem ser úteis. No exemplo específico do OP (um conjunto de rotinas matemáticas), se ele desejasse a capacidade de especificar parâmetros - digamos, um tipo de dados principal e precisão de saída - que seriam aplicados a todas as rotinas, ele poderia fazer algo como:
Se você não precisa que, em seguida, por todos os meios utilizar um espaço de nomes.
fonte
template
argumentos!Você deve usar um espaço para nome, porque um espaço para nome tem muitas vantagens sobre uma classe:
using
um membro da classe; você podeusing
um membro do espaço para nomeusing class
, emborausing namespace
nem sempre seja uma boa ideiaMembros estáticos são, na minha opinião, muito, muito usados. Eles não são uma necessidade real na maioria dos casos. As funções de membros estáticos provavelmente são melhores como funções de escopo de arquivo, e os membros de dados estáticos são apenas objetos globais com uma reputação melhor e não merecida.
fonte
inline
palavra-chave para satisfazer o ODR.inline
, e NÃO é "embutido" no corpo de uma função. O objetivo real (e garantido pelo padrão) doinline
é impedir várias definições. Leia sobre "Regra de uma definição" para C ++. Além disso, a questão do SO vinculado não estava sendo compilada devido a problemas de cabeçalho pré-compilado em vez de problemas de ODR.Eu preferiria os espaços para nome, dessa forma, você pode ter dados privados em um espaço para nome anônimo no arquivo de implementação (para que ele não precise aparecer no cabeçalho, em oposição aos
private
membros). Outro benefício é que, pelousing
seu namespace, os clientes dos métodos podem optar por não especificarMyMath::
fonte
Mais um motivo para usar a classe - Opção para fazer uso de especificadores de acesso. Em seguida, é possível quebrar seu método estático público em métodos particulares menores. O método público pode chamar vários métodos particulares.
fonte
private
método mais é mais acessível que um método cujo protótipo não é publicado em nenhum cabeçalho (e, portanto, permanece invisível). Não estou nem mencionando o melhor encapsulamento oferecido por funções anônimas no espaço de nomes..cpp
arquivo, o que tornaria privado a unidade de tradução sem fornecer informações supérfluas a quem estiver lendo o arquivo de cabeçalho. Efetivamente, estou tentando defender o idioma do PIMPL..cpp
arquivo se desejar usar modelos.O espaço para nome e o método de classe têm seus usos. O espaço para nome tem a capacidade de se espalhar pelos arquivos, no entanto, isso é um ponto fraco se você precisar aplicar todo o código relacionado para que ele vá em um arquivo. Como mencionado acima, a classe também permite criar membros estáticos privados na classe. Você pode tê-lo no espaço para nome anônimo do arquivo de implementação, no entanto, ainda é um escopo maior do que tê-lo dentro da classe.
fonte
private:
outras. e em muitos casos em que o acesso privilegiado parece ser necessário, isso pode ser fatorado. a função mais 'privada' é aquela que não aparece em um cabeçalho.private:
Os métodos nunca podem usufruir desse benefício.