C ++: Ad alanları - Başlık ve kaynak dosyalarında nasıl doğru şekilde kullanılır?


90

Bir çift kaynak dosyası düşünün: bir arayüz bildirim dosyası ( *.hveya *.hpp) ve uygulama dosyası ( *.cpp).

*.hDosya aşağıdaki gibi olsun :

namespace MyNamespace {
  class MyClass {
  public:
    int foo();
  };
}

Kaynak dosyalarda ad alanlarını kullanmak için iki farklı uygulama gördüm:

*.cpp 1. uygulamayı göstermek:

#include "MyClass.h"
using namespace MyNamespace;

int MyClass::foo() { ... }

*.cpp 2. uygulamayı göstermek:

#include "MyClass.h"
namespace MyNamespace {

  int MyClass::foo() { ... }

}

Sorum: Bu iki uygulama arasında herhangi bir fark var mı ve biri diğerinden daha iyi kabul ediliyor mu?


30
Ayrıca 3. seçenek de var: Tam adı sadece biz, ör int MyNamespace::MyClass::foo() ....
Benjamin Bannier


@Dave yinelenmemiş. Bu sorular birbirini tamamlıyor. Dave tarafından sağlanan bağlantıyı bu soruya "Ayrıca oku ..." olarak eklemenizi öneririz. Sorum acemilerin doğru stili seçmelerine yardımcı olacak.
nickolay

Yanıtlar:


65

Kod okunabilirliği açısından, bence bu nedenle # 2 yöntemini kullanmak muhtemelen daha iyidir:

Aynı anda usingbirden fazla ad alanı olabilirsiniz ve bu satırın altına yazılan herhangi bir nesne veya işlev bu ad alanlarından herhangi birine ait olabilir (adlandırma çakışmaları dışında). Tüm dosyanın bir namespacebloğa sarılması daha belirgindir ve .cpp dosyası içinde bu ad alanına ait olan yeni işlevleri ve değişkenleri de bildirmenize olanak tanır


Dave'in yorumunda sizin sorunuza bağladığı soru, baktığınız iki yöntem arasındaki farklılıkların (varsa) bazı temel noktalarını da özetlemektedir
Dan F

Beyler, kimin cevabını seçeceğimi gerçekten bilmiyorum. Birbirlerini tamamlarken kesişiyorlar.
nickolay

CLion gibi bazı IDE'lerin yalnızca 2. seçeneği / uygulamayı kullanırsanız uygulamaları algılayacağını kabul etmek için yorum yapmak yeterli.
pedrostanaka

@PedroTanaka bu hala böyle mi? Böyle bir sorun fark etmedim.
John McFarlane

@JMcF Yorumu yayınladığımdan beri kontrol etmedim. Clion'un ilk sürümlerinde sorun ortaya çıktı.
pedrostanaka

52

En net olanı, göstermediğiniz seçenektir:

int MyNamespace::MyClass::foo()
{
    //  ...
}

Aynı zamanda çok ayrıntılı; çoğu insan için çok fazla. Beri using namespacebenim durumumda en azından isim çakışmaları bir recepe, ve çok sınırlı kapsamları ve yerler haricinde kaçınılmalıdır, ben genellikle # 2'yi kullanmak.


4
Çok açık teşekkürler. Birlikte ad alanı kullanıcıları için iyi bir SSS sayfası yaptık. :)
nickolay

2
Beyler, kimin cevabını seçeceğimi gerçekten bilmiyorum. Birbirlerini tamamlarken kesişiyorlar.
nickolay

10

Bu iki uygulama arasında herhangi bir fark var mı

Evet. # 1 ve # 2, sırasıyla bir kullanım yönergesi ve bir ad alanı tanımı örnekleridir . Bu durumda bunlar fiilen aynıdır ancak başka sonuçları vardır. Örneğin, birlikte yeni bir tanımlayıcı eklerseniz MyClass::foo, farklı bir kapsamı olacaktır:

# 1:

using namespace MyNamespace;
int x;  // defines ::x

# 2:

namespace MyNamespace {
  int x;  // defines MyNamespace::x
}

biri diğerinden daha iyi kabul edilir mi?

# 1 Artıları: biraz daha özlü; istemeden bir şeyi kazara sokmak daha zordur MyNamespace. Eksileri: istemeden mevcut tanımlayıcıları çekebilir.

# 2 Artıları: mevcut tanımlayıcıların tanımlarının ve yeni tanımlayıcıların bildirimlerinin her ikisinin de ait olduğu daha açık MyNamespace. Eksileri: istemeden tanımlayıcıları tanıtmak daha kolaydır MyNamespace.

Hem # 1 hem de # 2'nin eleştirisi, muhtemelen sadece üyelerinin tanımını önemsediğinizde tüm bir ad alanına atıfta bulunmalarıdır MyNamespace::MyClass. Bu ağırdır ve niyeti kötü bir şekilde iletir.

# 1'e olası bir alternatif , yalnızca ilgilendiğiniz tanımlayıcıyı içeren bir kullanım beyanıdır :

#include "MyClass.h"
using MyNamespace::MyClass;

int MyClass::foo() { ... }

5

Bir cpp dosyasında bir şablon uzmanlığı uygulamaya herhangi bir nedenle karar verirseniz ve yalnızca using namespacesize güvenirseniz , aşağıdaki sorunla karşılaşacağınızı da eklemek isterim :

// .h file
namespace someNameSpace
{
  template<typename T>
    class Demo
    {
      void foo();
    };
}

// .cpp file
using namespace someNameSpace;

template<typename T>
void Demo<T>::foo(){}

// this will produce
// error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive]
template<>
void Demo<int>::foo(){}

Aksi takdirde # 2 yöntemi uygularsanız bu iyi olacaktır.


0

Using-declaration kullanarak bir yol daha eklemek istiyorum :

#include "MyClass.h"
using MyNamespace::MyClass;

int MyClass::foo() { ... }

Bu yol, sınıfın birçok işlevi varsa, sizi birçok kez ad alanı adını yazmaktan kurtarır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.