Pergunta

Por que precisamos de ambos usando namespace e incluem directivas em programas em C ++?

Por exemplo,

#include <iostream>

using namespace std;

int main() {
 cout << "Hello world";
}

Por que não é suficiente apenas ter #include ou apenas ter "usando namespace std" e livrar-se do outro?

(Estou pensar em uma analogia com Java, java.net importação. * Irá importar importação tudo de java.net, você não precisa fazer mais nada.)

Foi útil?

Solução

Em C++ os conceitos são separados. Isso ocorre por design e útil.

Você pode incluir coisas que sem namespaces seria ambíguo.

Com namespaces você pode referir-se a duas classes diferentes que têm o mesmo nome. É claro que, nesse caso, você não deve usar a diretiva using ou se você fez, você teria que especificar o namespace das outras coisas no espaço de nomes que você queria.

Observe também que você não precisa do uso - você pode apenas utilizar std :: cout ou o que você precisa acesso. Você prefaciar os itens com o namespace.

Outras dicas

Usando directivas e incluem diretivas de pré-processamento são duas coisas diferentes. O include corresponde aproximadamente à variável de ambiente CLASSPATH de Java, ou a opção -cp da máquina virtual java.

O que ele faz é fazer os tipos conhecidos para o compilador. Apenas incluindo <string> por exemplo, irá torná-lo capaz de se referir a std::string:

#include <string>
#include <iostream>

int main() {
    std::cout << std::string("hello, i'm a string");
}

Agora, usando diretivas são como import em Java. Eles fazem nomes visíveis no escopo em que aparecem no, para que você não tem que qualificar-los plenamente anymore. Como em Java, nomes usados ??devem ser conhecidos antes de serem tornados visíveis:

#include <string> // CLASSPATH, or -cp
#include <iostream>

// without import in java you would have to type java.lang.String . 
// note it happens that java has a special rule to import java.lang.* 
// automatically. but that doesn't happen for other packages 
// (java.net for example). But for simplicity, i'm just using java.lang here.
using std::string; // import java.lang.String; 
using namespace std; // import java.lang.*;

int main() {
    cout << string("hello, i'm a string");
}

É de má prática para usar uma diretiva usando em arquivos de cabeçalho, porque isso significa que todos os outros arquivos fonte que acontece a incluí-lo vai ver esses nomes usando pesquisa de nome não qualificado. Ao contrário de Java, onde você só fazer nomes visíveis para o pacote a linha de importação aparece, Em C ++ que pode afetar todo o programa, se incluir esse arquivo diretamente ou indiretamente.

Tenha cuidado ao fazê-lo no escopo global, mesmo em arquivos de implementação. É melhor usá-los como local quanto possível. Para std namespace, eu nunca usar isso. I, e muitas outras pessoas, apenas sempre escrever std:: na frente de nomes. Mas se tiver que fazê-lo, fazê-lo como este:

#include <string>
#include <iostream>

int main() {
    using namespace std;
    cout << string("hello, i'm a string");
}

Para quais são namespaces e porque você precisa deles, leia a proposta Bjarne Stroustrup deu 1993, para adicioná-los para o próximo padrão C ++. É bem escrito:

http: //www.open- std.org/jtc1/sc22/wg21/docs/papers/1993/N0262.pdf

C ++ #include e utilizando ter funções diferentes.

puts #include o texto do arquivo incluído em seu arquivo de origem (na verdade unidade de tradução ) , namespaces, por outro lado são apenas um mecanismo para ter nomes exclusivos para que as pessoas diferentes podem criar um objeto "foo".

Isto vem de C ++ não ter o conceito de um módulo.

Tenha em mente que namespaces em C ++ estão abertos, o que significa que diferentes arquivos pode definir diferentes partes do mesmo namespace (algo como classes parciais de .NET).

//a.h
namespace eg {
    void foo();
}

//b.h
namespace eg {
    void bar();
}

A incluem está a definir a existência de funções.

O uso está tornando mais fácil usá-los.

cout conforme definido no iostream é realmente chamado "std :: cout".

Você poderia evitar o uso do espaço de nomes por escrito.

std::cout << "Hello World";

Essas palavras-chave são utilizados para fins diferentes.

A palavra-chave usando torna um nome de um namespace disponível para uso na atual região declarativa. Sua principalmente por conveniência, para que você não tem que usar o nome completo o tempo todo. Este página explica que em alguns detalhes.

A instrução #include é uma directiva processador pré e conta a pré-processador para tratar o conteúdo de um arquivo especificado como se esses conteúdos tinha aparecido no programa de origem no ponto onde as aparece directiva. Ou seja, você pode pensar desta declaração como copiar o arquivo incluído no atual. O compilador, em seguida, compila o arquivo inteiro como se você escreveu todo o código em um arquivo grande.

Eu acho que as outras respostas estão faltando o ponto um pouco. Em todos C ++, Java e C #, a coisa using / import é totalmente opcional. Então isso não é diferente.

E então você tem que fazer alguma coisa para código make ser de qualquer maneira visível, em todas as três plataformas.

Em C ++, você minimamente tem que incluí-lo na actual unidade de tradução (bom o suficiente para muitas implementações de vetoriais, corda, etc.), muitas vezes você tem que adicionar algo ao seu vinculador bem, embora algumas bibliotecas fazer isso automaticamente baseado no incluir (por exemplo impulso ao construir no Windows).

E em C # você tem que adicionar uma referência para o outro conjunto. Que cuida do equivalente a inclui e as configurações da ligação.

E, em Java você tem que garantir o código está no classpath, por exemplo, adicionar o jar relevante para ele.

Portanto, há muito de perto as coisas análogas necessárias em todas as três plataformas, ea separação entre using / import (a conveniência) e resolução de ligação real (uma exigência) é o mesmo em todos os três.

Como apontado, C ++ e Java são linguagens diferentes, e fazer as coisas um pouco diferentes. Além disso, C ++ é mais uma 'brincadeira cresceu' linguagem e Java mais de uma linguagem projetada.

Enquanto using namespace std; não é necessariamente uma má idéia, usando-o para todos os namespaces irá eliminar todo o benefício. Namespaces existem para que você pode escrever módulos sem levar em conta conflitos de nome com outros módulos, e using namespace this; using namespace that; pode criar ambiguidades.

Você precisa entender namespaces se você quiser realmente entender isso.

Com include você está apenas inclusive o arquivo de cabeçalho.

Com using namespace você está declarando que você está usando um determinado espaço de nomes que contém coisas como cout. por isso, se você fizer isso:

using namespace std;

para você usar cout você pode apenas fazer

cout << "Namespaces are good Fun";

em vez de:

std::cout << "Namespaces are Awesome";

Note que se você não #include <iostream> você não será capaz de usar nem std::cout nem cout em suas declarações e assim por diante, porque você não está incluindo o cabeçalho.

Um forro (não que isso é algo novo:)):

usando std permite omitir std :: prefixo, mas você não pode usar cout em tudo sem iostream .

Mesmo Stroustrup refere-se ao mecanismo de #include como um tanto hackish. No entanto ele faz compilação separada muito mais fácil (navio compilado bibliotecas e cabeçalhos em vez de todo o código fonte).

A questão realmente é "por que C ++ - depois que ele já tinha o mecanismo #include -? Namespaces add"

O melhor exemplo que conheço sobre o porquê #include não é suficiente vem da Sun. Aparentemente, os desenvolvedores Sun teve alguns problemas com um de seus produtos, porque eles tinham escrito uma função mktemp() que passou a ter a mesma assinatura como uma função mktemp() que foi incluído por meio de um arquivo que foi ela própria incluída através de um conector do projeto realmente queria.

É claro que as duas funções não eram compatíveis, e não poderia ser usado como um substituto para o outro. Por outro lado, o compilador e vinculador não percebi isso ao construir o binário, e às vezes mktemp() chamaria uma função, e às vezes ele iria chamar outro, com base na ordem diferentes arquivos foram compilados ou vinculados.

O problema decorre do fato de que C ++ foi originalmente compatível com - e, essencialmente, piggy-apoiada em cima de - C. E C tem apenas um espaço de nomes global. C ++ resolveu este problema - no código que não é compatível com C -. Através de namespaces

Tanto o C # e Java (1) tem um mecanismo de namespace (namespace em C #, package em Java), (2) são normalmente desenvolvidas através IDEs que pega referentes aos binários para o desenvolvedor, e (3) não permitem independentes funções (um escopo de classe é algo de um namespace, e reduz o risco de poluir o namespace global) para que eles tenham uma solução diferente para este problema. No entanto, ainda é possível ter alguma ambiguidade sobre qual o método que você está chamando (digamos, um conflito de nomes entre duas interfaces que uma classe herda), e nesse caso todos os três idiomas requerem o programador para especificar claramente qual o método que está realmente procurando, geralmente, antecedendo o nome da classe pai / interface.

Em C ++, a incluir directiva irá copiar e colar o arquivo de cabeçalho em seu código fonte na etapa de pré-processamento. Deve-se notar que um arquivo de cabeçalho geralmente contém funções e classes declaradas dentro de um namespace. Por exemplo, o cabeçalho <vector> pode ser semelhante a algo como isto:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
} 

Supondo que você precisa para definir um vector em sua função principal, você faz #include <vector> e você tem o pedaço de código acima em seu código agora:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
}
int main(){
   /*you want to use vector here*/
}

Observe que em seu código da classe vector é ainda localizado no namespace std. No entanto, a sua principal função é no namespace global padrão, tão simplesmente incluindo o cabeçalho não vai fazer a classe vector visível no namespace global. Você tem que quer using uso ou não prefixar como std::vector.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top