Hoe ga je goed namespaces in C ++ gebruiken?

stemmen
221

Ik kom uit een Java achtergrond, waar de verpakkingen worden gebruikt, niet namespaces. Ik ben gewend om klassen die samenwerken om een ​​compleet object in verpakkingen te vormen, en vervolgens het hergebruik van hen later van dat pakket. Maar nu ben ik werkzaam in C ++.

Hoe ga je namespaces in C ++ gebruiken? Heeft u een enkele namespace voor de hele toepassing te maken, of heb je namespaces voor de belangrijkste componenten te creëren? Zo ja, hoe doe je objecten uit de klassen in andere naamruimten?

De vraag is gesteld op 03/09/2008 om 11:54
user
In andere talen...                            


15 antwoorden

stemmen
160

Namespaces zijn pakketten wezen. Ze kunnen worden gebruikt als volgt:

namespace MyNamespace
{
  class MyClass
  {
  };
}

Vervolgens in code:

MyNamespace::MyClass* pClass = new MyNamespace::MyClass();

Hoop dat het helpt.

Of, als u wilt altijd gebruik maken van een bepaalde namespace, kunt u dit doen:

using namespace MyNamespace;

MyClass* pClass = new MyClass();

Edit: Na wat bernhardrusch heeft gezegd, heb ik de neiging niet te vergeten de "using namespace x" syntax te gebruiken op alle, ik meestal expliciet de namespace bij het concretiseren van mijn objecten (dat wil zeggen het eerste voorbeeld I liet zien).

En als je vroeg hieronder , kunt u zoveel namespaces gebruiken als u wilt.

antwoordde op 03/09/2008 om 11:57
bron van user

stemmen
3

Over het algemeen maak ik een namespace voor een lichaam van de code als ik geloof dat er misschien mogelijk zijn functie of typenaam conflicten met andere bibliotheken. Het helpt ook om het merk code, ala boost :: .

antwoordde op 03/09/2008 om 12:00
bron van user

stemmen
3

Ik geef de voorkeur gebruik van een top-level namespace voor de toepassing en sub namespaces voor de componenten.

De manier waarop je kunt klassen van andere naamruimten is verrassend zeer vergelijkbaar met de manier waarop in java. U kunt gebruik maken van "use NAMESPACE" die vergelijkbaar is met een "import PAKKET" statement, bijvoorbeeld het gebruik std. Of u opgeeft het pakket als voorvoegsel van de klasse, gescheiden door "::", bijvoorbeeld std :: string. Dit is vergelijkbaar met "java.lang.String" in Java.

antwoordde op 03/09/2008 om 12:00
bron van user

stemmen
5

@ Marius

Ja, u kunt meerdere naamruimten tegelijk gebruiken, bijvoorbeeld:

using namespace boost;   
using namespace std;  

shared_ptr<int> p(new int(1));   // shared_ptr belongs to boost   
cout << "cout belongs to std::" << endl;   // cout and endl are in std

[Februari 2014 - (Is het echt zo lang geleden?): Dit specifieke voorbeeld is nu dubbelzinnig, zoals Joey wijst erop hieronder. Boost en std :: nu hebben elk een shared_ptr.]

antwoordde op 03/09/2008 om 12:08
bron van user

stemmen
11

In Java:

package somepackage;
class SomeClass {}

In C ++:

namespace somenamespace {
    class SomeClass {}
}

En het gebruik ervan, Java:

import somepackage;

En C ++:

using namespace somenamespace;

Ook zijn volledige namen zijn "somepackge.SomeClass" voor Java en "somenamespace :: SomeClass" voor C ++. Met behulp van deze verdragen, kunt u organiseren zoals u gewend bent in Java, met inbegrip van het maken van de aanpassing van de map namen voor naamruimten. De folder-> pakket en file-> klasse eisen zijn er niet, dus u uw mappen en zelfstandig in klassen uit pakketten en naamruimten kunnen noemen.

antwoordde op 03/09/2008 om 12:09
bron van user

stemmen
112

Om te zeggen dat alles te voorkomen Mark Ingram zei al een kleine tip voor het gebruik van naamruimten:

Vermijd de "using namespace" richtlijn in header-bestanden - dit opent de namespace voor alle onderdelen van het programma, dat deze header bestand te importeren. In implementatie-bestanden (* .cpp) dit is normaal gesproken geen groot probleem - hoewel ik de voorkeur aan de "using namespace" richtlijn te gebruiken op het functieniveau.

Ik denk dat namespaces worden meestal gebruikt om naamgeving conflicten te voorkomen - niet per se uw code structuur te organiseren. Ik zou C ++ programma's organiseren vooral met header files / de bestandsstructuur.

Soms namespaces worden gebruikt in de grotere C ++ projecten ter implementatie details te verbergen.

Bijkomende nota aan de gebruikende richtlijn: Sommige mensen gebruiken liever "met behulp van" alleen voor enkele elementen:

using std::cout;  
using std::endl;
antwoordde op 03/09/2008 om 12:10
bron van user

stemmen
18

Merk ook op dat u kunt toevoegen aan een namespace. Dit is duidelijker met een voorbeeld, wat ik bedoel is dat je kunt hebben:

namespace MyNamespace
{
    double square(double x) { return x * x; }
}

in een bestand square.h, en

namespace MyNamespace
{
    double cube(double x) { return x * x * x; }
}

in een bestand cube.h. Dit definieert een enkele namespace MyNamespace(dat wil zeggen, kunt u een enkele namespace over meerdere bestanden definiëren).

antwoordde op 03/09/2008 om 12:17
bron van user

stemmen
3

Merk op dat een namespace in C ++ is eigenlijk gewoon een naam van de ruimte. Ze geven geen van de inkapseling die pakketten te doen in Java, zodat u waarschijnlijk zal ze niet zo veel gebruiken.

antwoordde op 03/09/2008 om 12:19
bron van user

stemmen
2

Ik heb gebruikt C ++ naamruimten dezelfde manier als ik doen in C #, Perl, enz. Het is gewoon een semantische scheiding van symbolen tussen standaard bibliotheek stuff, third party spul, en mijn eigen code. Ik zou mijn eigen app te plaatsen in een namespace, dan is een herbruikbare bibliotheek component in een ander namespace voor de scheiding.

antwoordde op 03/09/2008 om 12:38
bron van user

stemmen
2

Een ander verschil tussen Java en C ++, is dat in C ++, de naamruimtehiërarchie niet nodig om het bestandssysteem layout mach. Dus heb ik de neiging om een ​​volledige bibliotheek voor toekomstig gebruik in een enkele naamruimte en subsystemen binnen de bibliotheek in submappen te zetten:

#include "lib/module1.h"
#include "lib/module2.h"

lib::class1 *v = new lib::class1();

Ik zou alleen zet de subsystemen in geneste namespaces als er een mogelijkheid van een naam conflict.

antwoordde op 03/09/2008 om 13:42
bron van user

stemmen
5

U kunt ook bevatten "using namespace ..." in een functie bijvoorbeeld:

void test(const std::string& s) {
    using namespace std;
    cout << s;
}
antwoordde op 03/09/2008 om 13:59
bron van user

stemmen
36

Bigger C ++ projecten die ik heb gezien nauwelijks gebruikt meer dan een namespace (bijv boost bibliotheek).

Eigenlijk boost maakt gebruik van tal van namespaces, meestal om een ​​deel van boost heeft zijn eigen namespace voor de interne werking en dan mag alleen de openbare interface zet in de top-level namespace boost.

Persoonlijk denk ik dat hoe groter een code-base wordt, des te belangrijker naamruimten geworden, zelfs binnen een enkele applicatie (of bibliotheek). Op het werk zetten we elke module van onze applicatie in zijn eigen namespace.

Een ander gebruik (no pun intended) van naamruimten dat ik veel gebruik is de anonieme namespace:

namespace {
  const int CONSTANT = 42;
}

Dit is in principe hetzelfde als:

static const int CONSTANT = 42;

Via een anonieme naamruimte (in plaats van statisch) echter de beste manier om code en gegevens alleen zichtbaar zijn in de huidige compilatie eenheid C ++.

antwoordde op 06/09/2008 om 23:31
bron van user

stemmen
53

Luister niet naar elk volk te vertellen dat namespaces zijn namespaces.

Ze zijn belangrijk omdat ze door de compiler worden beschouwd als de interface toe te passen. In principe kan worden verklaard door een voorbeeld:

namespace ns {

class A
{
};

void print(A a)
{
}

}

Als je wilde een A object af te drukken, zou de code deze zijn:

ns::A a;
print(a);

Merk op dat we de namespace niet expliciet te vermelden bij het aanroepen van de functie. Dit is de interface principe: C ++ overwegen een functie het nemen van een type als een argument als onderdeel van de interface voor dat type, dus geen noodzaak om de namespace specificeren, omdat de parameter al de namespace geïmpliceerd.

Nu waarom dit principe is belangrijk? Stel je voor dat de klasse A auteur geen functie print () voor deze klasse hebben verstrekt. Je moet er zelf een te bieden. Als je een goede programmeur, zul je deze functie te definiëren in uw eigen naamruimte, of misschien in de global namespace.

namespace ns {

class A
{
};

}

void print(A a)
{
}

En uw code kunt beginnen met het aanroepen van de afdruk (a) functie waar u maar wilt. Stel je nu voor dat jaar later, de auteur beslist om een ​​print () functie, beter dan de jouwe te bieden omdat hij weet dat het inwendige van zijn klasse en kan een betere versie te maken dan de jouwe.

Dan C ++ auteurs besloten dat zijn versie van de functie print () moet worden gebruikt in plaats van de ene in een andere namespace, om de interface te eerbiedigen. En dat deze "upgrade" van de functie print () moet zo eenvoudig mogelijk te maken, wat betekent dat je niet hoeft te elk gesprek wijzigen om de print () functie zijn. Dat is de reden waarom "interface-functies" (functie in dezelfde namespace als een klasse) kan worden genoemd zonder vermelding van de namespace in C ++.

En dat is waarom je zou moeten overwegen een C ++ namespace als een "-interface" als je een te gebruiken en rekening houden met de interface principe.

Als je een betere verklaring voor dit gedrag wilt, kunt u verwijzen naar het boek Uitzonderlijke C ++ van Herb Sutter

antwoordde op 07/09/2008 om 00:26
bron van user

stemmen
75

Vincent Robert heeft gelijk in zijn commentaar Hoe ga je goed namespaces gebruiken in C ++? .

Met behulp van namespace

Namespaces worden gebruikt op zijn minst te helpen voorkomen dat de naam botsing. In Java, wordt dit afgedwongen via de "org.domain" idioom (omdat het wordt verondersteld zal men geen gebruik maken van iets anders dan zijn / haar eigen domeinnaam).

In C ++, kunt u een namespace om alle code te geven in uw module. Bijvoorbeeld voor een module MyModule.dll, kon je de code de namespace MyModule geven. Ik heb elders iemand die MyCompany :: MyProject :: MyModule zien. Ik denk dat dit is overkill, maar al met al, lijkt het juist voor mij.

Met behulp van "gebruiken"

Het gebruik moet worden gebruikt met grote zorg, omdat het effectief één (of alle) symbolen uit een namespace importeren in uw huidige namespace.

Dit is kwaad om het te doen in een header-bestand, omdat uw header elke bron, waaronder het (het doet me denken aan macro's, ...) zal vervuilen, en zelfs in een bronbestand, slechte stijl buiten een functie scope omdat het importeren op mondiaal bereik de symbolen van de namespace.

De meest veilige manier te gebruiken "gebruiken" is het selecteren symbolen importeren:

void doSomething()
{
   using std::string ; // string is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   std::cout << a << std::endl ;
}

void doSomethingElse()
{
   using namespace std ; // everything from std is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   cout << a << endl ;
}

Je zult een hoop te zien "using namespace std;" tutorial of voorbeeld codes. De reden hiervoor is om het aantal symbolen te verminderen om het lezen te vergemakkelijken, niet omdat het een goed idee.

"namespace std; gebruiken ;" wordt ontmoedigd door Scott Meyers (ik weet niet meer precies welk boek, maar ik kan het vinden indien nodig).

namespace Samenstelling

Namespaces zijn meer dan pakketten. Een ander voorbeeld is te vinden in Bjarne Stroustrup "The C ++ Programming Language".

In de "Special Edition", op 8.2.8 Namespace Composition , beschrijft hij hoe je twee namespaces AAA en BBB kunnen opgaan in een andere genaamd CCC. Aldus CCC wordt een alias voor zowel AAA en BBB:

namespace AAA
{
   void doSomething() ;
}

namespace BBB
{
   void doSomethingElse() ;
}

namespace CCC
{
   using namespace AAA ;
   using namespace BBB ;
}

void doSomethingAgain()
{
   CCC::doSomething() ;
   CCC::doSomethingElse() ;
}

Je zou zelfs kunnen selecteren symbolen importeren uit verschillende naamruimten, om uw eigen aangepaste namespace-interface te bouwen. Ik heb nog een praktisch gebruik van deze te vinden, maar in theorie is het cool.

antwoordde op 17/09/2008 om 08:56
bron van user

stemmen
67

Ik heb geen melding gemaakt van het niet zien in de andere antwoorden, dus hier zijn mijn 2 Canadese cent:

Op de "using namespace" onderwerp, een goed overzicht is de namespace alias, zodat u "hernoemen" een namespace, normaal gesproken om het een kortere naam geven. Bijvoorbeeld, in plaats van:

Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::TheClassName foo;
Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::AnotherClassName bar;

je kan schrijven:

namespace Shorter = Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally;
Shorter::TheClassName foo;
Shorter::AnotherClassName bar;
antwoordde op 21/10/2009 om 12:19
bron van user

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more