Pergunta

Eu ainda estou aprendendo C ++, e eu nunca realmente criei o meu próprio namespaces antes. Eu estava experimentando com eles e, enquanto eu tenho a maioria das coisas para o trabalho, há uma coisa que eu ainda não consigo fazer. Eu gostaria de ser capaz de chamar um método estático dentro de uma classe sem digitar algo como NameOfClass::method. Aqui está o que eu pensei que o código deve ser semelhante, mas falha ao compilar:

A.h arquivo,

namespace Test
{
    class A
    {
        public:
            static int foo() { return 42; }
    };
}

main.cpp arquivo,

#include <iostream>

#include "A.h"

using namespace std;
using namespace Test::A;

int main()
{
    cout << foo() << endl;

    return 0;
}

O compilador me dá:

main.cpp:6: error: ‘A’ is not a namespace-name
main.cpp:6: error: expected namespace-name before ‘;’ token
main.cpp: In function ‘int main()’:
main.cpp:10: error: ‘foo’ was not declared in this scope

É possível fazer o que eu estou tentando fazer, sem A::foo digitação?

Foi útil?

Solução

Não há maneira de contornar isso é preciso especificar o nome da classe de métodos estáticos.

using namespace Test;

Depois:

int answerToEverything = A::foo();

Outras dicas

Em C ++, você / especialmente / tem que ler as mensagens de erro do compilador com cuidado.

Observe o primeiro erro foi "erro:‘A’não é um nome de espaço de nomes". Isso é verdade, A é um nome de classe.

using namespace Foo; // brings in  all of foo;
using Bar::Baz // brings in only Baz from Bar

Você quer escrever:

using Test::A;

Isso faz duas coisas boas: ele traz um para você usar, e não traz em todo o resto do teste, o que é bom também, porque você só deve trazer o que você precisa, de modo a não acidentalmente depender de algo que você não percebe que você está dependendo.

No entanto, como foo é estática em A, você ainda tem para se referir a A :: foo explicitamente. (A menos que você fizer algo como escrever uma função livre que encaminha para A :: foo;., Em geral, esta é uma má idéia se você está fazendo isso apenas para poupar algum digitação)

Alguns podem aconselhar não usar usando declarações em tudo, em vez qualificar totalmente todos os nomes.

Mas este é (para citar Stroustrup) "tedioso e propenso a erros", e que fica no caminho de refatoração: digamos que você qualificar totalmente cada uso de classe foomatic :: Stack, e em seguida, gestão insiste, pouco antes de você' re prestes a ir para a produção, o uso de classe Stack muito semelhante do BarMatic, porque barMatic apenas comprou a sua empresa.

Se você tivesse totalmente qualificado em todos os lugares, você estaria fazendo um monte de grepping, esperando a sua regex estava certo. Se você usou uma declaração usando, você pode apenas fazer uma correção para a sua (espero compartilhada) arquivo de cabeçalho. Desta forma, uma declaração usando é muito parecido com um "typedef int ourInt;" ou uma constante manifesto ou const: "int FOO const = 1;", na medida em que fornece um lugar para mudar algo que é referido muitos lugares. Totalmente qualificação de um namespace em cada utilização tira esse benefício.

Por outro lado, se você tivesse usado uma utilizando directiva e trouxe em todos Namespace foomatic, o grep poderia ter sido ainda mais difícil, se a administração digamos insistiu em BarMatic :: Foo mas você ainda tinha que usar foomatic: Baz, o equivalente BarMatic para Baz ser por qualquer motivo inutilizável.

Assim, trazendo em um tipo (classe, função, constante) em um momento é geralmente o mais flexível, o caminho para melhor se proteger contra mudanças inevitáveis, mas ainda desconhecidos. Como na maior parte de codificação, que pretende minimizar a repetição tediosa, mantendo granularidade suficiente.

Não, não é possível fazer o que você está tentando fazer de qualquer forma elegante. A coisa mais próxima que você vai ser capaz de fazer é criar um macro ou uma função inline que delega à sua função. No entanto, ambas as alternativas são bastante feio, então eu não vou postar qualquer exemplos de código. Apenas morder a bala e especificar o nome inteiro, ou refatorar seu código para que os métodos estáticos são apenas funções globais.

Não seja um "usando namespace" agressor. Use os espaços de nomes!

std::cout << Test::A::foo() << std::endl;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top