Beklenen çift kolon “::” ne anlama geliyor?


410

Ben değiştirmek zorunda bir sınıfta bir kod bu satırı bulundu:

::Configuration * tmpCo = m_configurationDB;//pointer to current db

ve sınıf adına eklenmiş çift kolonun tam olarak ne anlama geldiğini bilmiyorum. O olmadan şunu okurdum: tmpCosınıfın bir nesnesine bir işaretçi olarak bildirmek Configuration... ama baştaki çift kolon beni karıştırır.

Ayrıca buldum:

typedef ::config::set ConfigSet;

7
Bunun bir cevap olduğunu gerçekten hissetme, bu yüzden yorum yapacağım: en.wikipedia.org/wiki/Scope_resolution_operator . Bu bağlamda, çıplak ::araçlar genel / anonim ad alanından değişkene başvurur.
wkl

Yanıtlar:


490

Bu, çözümlemenin, içinde bulunduğunuz ad alanında başlamak yerine genel ad alanından gerçekleşmesini sağlar. Örneğin, şu şekilde adlandırılan iki farklı sınıfınız varsa Configuration:

class Configuration; // class 1, in global namespace
namespace MyApp
{
    class Configuration; // class 2, different from class 1
    function blah()
    {
        // resolves to MyApp::Configuration, class 2
        Configuration::doStuff(...) 
        // resolves to top-level Configuration, class 1
        ::Configuration::doStuff(...)
    }
}

Temel olarak, bu durumda, adınız başka bir ad alanının içindeki yeni bir tanımla tıkanabileceğinden, genel ad alanına kadar gitmenize izin verir MyApp.


2 set çift sütun koymanın nedeni nedir? Bu konuda:::Configuration::doStuff(...)
Azurespot 31:17

@NoniA. ikinci çift kolonun ne yaptığını mı soruyorsun?
FCo

1
@WyattAnderson, 1. set yok. ::Aradaki iki terimin ad alanı veya sınıf ve üyesini ifade ettiğini düşünüyorum . Peki ya birincisi?
Azurespot

6
@Azurespot OP'nin sorduğu şey, bu yazının cevapladığı soru bu. Genel ad alanındaki tanımlayıcıyı kullandığınızdan emin olur. Yine örneğe bakın
hungryWolf

193

::Operatör kapsamı çözünürlüklü operatörü denir ve kapsamını giderir sadece bunu yapar edilir. Bu nedenle, bununla bir tür adının önüne ekleyerek, derleyicinize türün genel ad alanına bakmasını söyler.

Misal:

int count = 0;

int main(void) {
  int count = 0;
  ::count = 1;  // set global count to 1
  count = 2;    // set local count to 2
  return 0;
}

122

Çok makul cevaplar zaten. Bazı okuyuculara yardımcı olabilecek bir benzetmeyle karşılaşacağım. çalıştırmak istediğiniz bir program için yol ararken ::` /` dosya sistemi dizin ayırıcısı ' ' gibi çok çalışır. Düşünmek:

/path/to/executable

Bu çok açıktır - yürürlükteki PATH ne olursa olsun, yalnızca dosya sistemi ağacındaki tam olarak bu konumdaki bir yürütülebilir dosya bu belirtimle eşleşebilir. Benzer şekilde...

::std::cout

... C ++ ad alanı "tree" de eşit derecede açıktır.

Böyle mutlak yollarla zıt, siz (örn iyi UNIX kabukları yapılandırabilirsiniz zsh çözümlemek için) göreli geçerli dizinde veya herhangi elemanın altında yolları PATHeğer öyleyse, ortam değişkeni PATH=/usr/bin:/usr/local/binve "" içinde olduklarını /tmp, sonra ...

X11/xterm

... /tmp/X11/xtermbaşka bulursa, mutlu bir şekilde /usr/bin/X11/xtermçalışırdı /usr/local/bin/X11/xterm. Benzer şekilde, adında bir ad alanında olduğunuzu Xve " using namespace Y" efekti olduğunu varsayalım.

std::cout

... hiçbirinde bulunamadı ::X::std::cout, ::std::cout, ::Y::std::coutnedeniyle, ve muhtemelen başka yerlerde bağımsız ve bağımlı arama (ADL, diğer adıyla Koenig arama). Yani, sadece ::std::couttam olarak hangi nesneyi kastettiğiniz konusunda gerçekten açıktır, ancak neyse ki, sağ akıllarında hiç kimse kendi sınıfını / yapısını veya " std" adı verilen bir ad alanını veya " " olarak adlandırılan herhangi bir şeyi yaratmaz cout, bu yüzden sadece pratikte kullanmak std::coutiyidir.

Dikkate değer farklılıklar :

1) mermiler, sıralamayı kullanarak ilk eşleşmeyi kullanma eğilimindedir PATH, oysa C ++ belirsiz olduğunuzda bir derleyici hatası verir.

En UNIX kabukları yalnızca koyarsanız bunu yaparken 2) C ++, herhangi lider kapsam olmadan isimleri, alanında isim eşleştirilebilir .içinde PATH.

3) C ++ her zaman genel ad alanında arama yapar ( /örtük olarak size ait gibi PATH).

İsim alanları ve sembollerin açıklığı hakkında genel tartışma

Mutlak ::abc::def::..."yollar" kullanmak bazen sizi kullandığınız diğer ad alanlarından ayırmak, kitaplığının istemci kodunun da kullandığı içeriklerin ve hatta diğer kitaplıkların içeriği üzerinde kontrol sahibi olamayabilir. Öte yandan, sizi sembolün mevcut "mutlak" konumuna daha sıkı bağlar ve ad alanlarında örtük eşleştirmenin avantajlarını kaçırırsınız: daha az eşleme, ad alanları arasında kodun daha kolay taşınabilirliği ve daha özlü, okunabilir kaynak kodu .

Birçok şeyde olduğu gibi, bu dengeleyici bir eylemdir. Altında tanımlayıcıları C ++ Standart koyar sürü std::daha az "benzersiz" olan coutprogramcılar kendi kodunda tamamen farklı bir şey için kullanmak olabilir, (örneğin merge, includes, fill, generate, exchange, queue, toupper, max). İlişkisiz iki Standart olmayan kütüphanenin, yazarlar genellikle birbirlerinden habersiz veya daha az farkında oldukları gibi aynı tanımlayıcıları kullanma şansı daha yüksektir. Ve C ++ Standart kütüphanesi de dahil olmak üzere kütüphaneler sembollerini zamanla değiştirir. Tüm bunlar, eski kodları derlerken özellikle de using namespaces'nin yoğun kullanımı olduğunda belirsizliğe neden olur : bu alanda yapabileceğiniz en kötü şey izinusing namespacebaşlıkların başlıklarından kaçmak için, keyfi olarak büyük miktarda doğrudan ve dolaylı istemci kodu hangi ad alanlarının kullanılacağı ve belirsizliklerin nasıl yönetileceği konusunda kendi kararlarını veremez.

Yani, bir lider ::C ++ programcı araç kutusunda bilinen bir çatışmayı aktif olarak belirsizleştirmek ve / veya gelecekteki belirsizlik olasılığını ortadan kaldırmak için bir araçtır ....


8
İyi benzetme için +1. analojiler bir öğretim aracı olarak neredeyse yeterince IMO kullanılmamaktadır.
Trevor Boyd Smith

38

::kapsam çözümleme operatörüdür. Bir şeyin kapsamını belirtmek için kullanılır.

Örneğin, ::tek başına küresel kapsam, diğer tüm ad alanlarının dışındadır.

some::thing aşağıdaki yollardan biriyle yorumlanabilir:

  • somebir ad alanıdır (global kapsamda veya geçerli alanın dışında bir dış kapsamdadır) vething bir tür , işlev , nesne veya iç içe geçmiş bir ad alanıdır ;
  • somebir sınıf mevcut kapsamda mevcut ve thinga, elemanı nesnesi , fonksiyon ya da tip bir somesınıfı;
  • Bir sınıf üyesi işlevinde , somebir olabilir, baz tipi geçerli türün (veya geçerli türün kendisinin) ve thingbu sınıfın bir üyesi, bir tür , işlev veya nesne olabilir .

İçindekiler gibi, iç içe geçmiş kapsam da olabilir some::thing::bad. Burada her ad bir tür, bir nesne veya bir ad alanı olabilir. Ayrıca, sonuncusu badda bir işlev olabilir. Diğerleri yapamadı, çünkü işlevler kendi iç kapsamları içinde hiçbir şeyi açığa çıkaramaz.

Örneğin, örneğinize geri dönersek, ::thingyalnızca global kapsamda bir şey olabilir: bir tür, bir işlev, bir nesne veya bir ad alanı.

Bunu kullanma şekliniz (işaretçi bildiriminde kullanılır), bunun global kapsamda bir tür olduğunu gösterir.

Umarım bu cevap kapsam çözümünü anlamanıza yardımcı olacak kadar eksiksiz ve doğrudur.


2
@obounaim bu kod düşünün liveworkspace.org/code/3Wabw0$5 class some { protected: int thing; }; class some_ext : public some { float thing; void action(){ some::thing = 42; thing = 666; } }; İşte somebir taban sınıfıdır some_extve yazarken some::thingsome_ext üyesi işlevleri içine, bunun anlamını thingtaban türü içine nesne some. Olmadan some::, thingtek başına thingen yakın kapsamda demektir some_ext::thing. Daha açık mı?
Klaim

17

:: bir şeyi (değişken, işlev, sınıf, typedef vb.) bir ad alanına veya bir sınıfa bağlamak için kullanılır.

::daha önce sol taraf yoksa, global ad alanını kullandığınızın altını çizer.

Örneğin:

::doMyGlobalFunction();


10

kapsam çözümleme operatörü olarak adlandırılır, Gizli bir küresel ad kapsam çözümleme operatörü kullanılarak ifade edilebilir ::
Örneğin;

int x;
void f2()
{
   int x = 1; // hide global x
   ::x = 2; // assign to global x
   x = 2; // assign to local x
   // ...
}

10

(Bu cevap çoğunlukla Google çalışanları içindir, çünkü OP sorununu zaten çözmüştür.) :: yanıt kapsamı operatörünün diğer cevaplarda açıklanmıştır, ancak insanların neden kullandığını eklemek istiyorum.

Anlamı "başka bir şey değil, küresel ad alanından isim almak". Ama bunun neden açıkça belirtilmesi gerekiyor?

Kullanım örneği - ad alanı çakışması

Genel ad alanında ve yerel / iç içe ad alanında aynı ada sahip olduğunuzda, yerel ad alanı kullanılır. Eğer küresel olanı istiyorsanız, onunla başa getirin ::. Bu dava @Wyatt Anderson'ın cevabında açıklandı, lütfen örneğine bakın.

Kullanım örneği - üye olmayan işlevi vurgula

Bir üye işlevi (yöntem) yazarken, diğer üye işlevlerine yapılan çağrılar ve üye olmayan (ücretsiz) işlevlere yapılan çağrılar birbirine benzer:

class A {
   void DoSomething() {
      m_counter=0;
      ...
      Twist(data); 
      ...
      Bend(data);
      ...
      if(m_counter>0) exit(0);
   }
   int m_couner;
   ...
}

Ancak Twist, sınıfın kardeş üye işlevi Ave Bendözgür bir işlev olabilir. Yani, Twistkullanabilir ve değiştirebilir m_counerve Bendyapamaz. Bu yüzden m_counter0 olarak kalmasını sağlamak istiyorsanız, kontrol etmeniz gerekir Twist, ancak kontrol etmeniz gerekmezBend .

Yani bunu daha açık bir şekilde ortaya this->Twistkoymak için Twist, bir üye işlevi olan okuyucuyu göstermek için ya da ücretsiz ::Bendolduğunu göstermek için yazı yazabilirsiniz Bend. Ya da her ikisi de. Bu, yeniden düzenleme yaparken veya planlarken çok faydalıdır.


5

:: ad alanını tanımlayan bir operatördür.

Örneğin, using namespace std;kodunuzda bahsetmeden cout kullanmak istiyorsanız, şunu yazabilirsiniz:

std::cout << "test";

Hiçbir ad alanı belirtilmediğinde, sınıfın genel ad alanına ait olduğu söylenir.


1

"::" kapsam çözümleme işlecini temsil eder. Aynı ada sahip işlevler / yöntemler iki farklı sınıfta tanımlanabilir. Belirli bir sınıfın yöntemlerine erişmek için çözünürlük operatörü kullanılı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.