Share via


Ad Alanları (C++)

Ad alanı, içindeki tanımlayıcılara (tür, işlev, değişken vb.) kapsam sağlayan bildirim temelli bir bölgedir. Ad alanları, kodu mantıksal gruplar halinde düzenlemek ve özellikle kod tabanınız birden çok kitaplık içerdiğinde oluşabilecek ad çakışmalarını önlemek için kullanılır. Ad alanı kapsamındaki tüm tanımlayıcılar, niteleme olmadan birbirleri tarafından görülebilir. Ad alanı dışındaki tanımlayıcılar, üyelere her tanımlayıcı için tam adı kullanarak erişebilir; örneğinstd::vector<std::string> vec;, tek bir tanımlayıcı için bir using Bildirimi () veya ad alanı içindekiusing std::string (using namespace std; içindeki tüm tanımlayıcılar için bir using Yönergesi). Üst bilgi dosyalarındaki kod her zaman tam ad alanı adını kullanmalıdır.

Aşağıdaki örnekte bir ad alanı bildirimi ve ad alanı dışındaki kodun üyelerine erişmesinin üç yolu gösterilmektedir.

namespace ContosoData
{
    class ObjectManager
    {
    public:
        void DoSomething() {}
    };
    void Func(ObjectManager) {}
}

Tam adı kullanın:

ContosoData::ObjectManager mgr;
mgr.DoSomething();
ContosoData::Func(mgr);

Bir tanımlayıcıyı kapsama getirmek için using bildirimini kullanın:

using ContosoData::ObjectManager;
ObjectManager mgr;
mgr.DoSomething();

Ad alanı içindeki her şeyi kapsama getirmek için bir using yönergesi kullanın:

using namespace ContosoData;

ObjectManager mgr;
mgr.DoSomething();
Func(mgr);

using yönergeleri

yönergesiusing, içindeki tüm adların namespace ad alanı-adı olmadan açık bir niteleyici olarak kullanılmasına izin verir. Bir ad alanında birkaç farklı tanımlayıcı kullanıyorsanız uygulama dosyasında (örneğin *.cpp) bir using yönergesi kullanın; yalnızca bir veya iki tanımlayıcı kullanıyorsanız, ad alanında tüm tanımlayıcıları değil, yalnızca bu tanımlayıcıları kapsama getirmek için bir using bildirimini göz önünde bulundurun. Yerel bir değişken adı ad alanı değişkeniyle aynı ada sahipse, ad alanı değişkeni gizlenir. Genel bir değişken olarak aynı ada sahip ad alanı değişkeninin bulundurulması bir hatadır.

Dekont

Using yönergesi bir .cpp dosyasının en üstüne (dosya kapsamında) veya bir sınıf veya işlev tanımının içine yerleştirilebilir.

Genel olarak üst bilgi dosyalarına (*.h) yönergelerini kullanmaktan kaçının, çünkü bu üst bilgiyi içeren tüm dosyalar ad alanı içindeki her şeyi kapsama alır ve bu da hata ayıklaması çok zor olan ad gizleme ve ad çakışması sorunlarına neden olabilir. Üst bilgi dosyasında her zaman tam adları kullanın. Bu adlar çok uzun olursa, kısaltmak için bir ad alanı diğer adı kullanabilirsiniz. (Aşağıya bakın.)

Ad alanlarını ve ad alanı üyelerini bildirme

Genellikle, bir üst bilgi dosyasında bir ad alanı bildirirsiniz. İşlev uygulamalarınız ayrı bir dosyadaysa, bu örnekte olduğu gibi işlev adlarını niteleyin.

// contosoData.h
#pragma once
namespace ContosoDataServer
{
    void Foo();
    int Bar();
}

contosodata.cpp dosyasındaki işlev uygulamaları, dosyanın en üstüne bir using yönerge yerleştirseniz bile tam adı kullanmalıdır:

#include "contosodata.h"
using namespace ContosoDataServer;

void ContosoDataServer::Foo() // use fully-qualified name here
{
   // no qualification needed for Bar()
   Bar();
}

int ContosoDataServer::Bar(){return 0;}

Ad alanı, tek bir dosyada ve birden çok dosyada birden çok blok halinde bildirilebilir. Derleyici, ön işleme sırasında bölümleri birleştirir ve sonuçta elde edilen ad alanı tüm bölümlerde bildirilen tüm üyeleri içerir. Bunun bir örneği, standart kitaplıktaki üst bilgi dosyalarının her birinde bildirilen std ad alanıdır.

Adlandırılmış ad alanının üyeleri, tanımlanmakta olan adın açık niteliğiyle bildirildikleri ad alanının dışında tanımlanabilir. Ancak tanım, bildirimin ad alanını kapsayan bir ad alanında bildirim noktasından sonra görünmelidir. Örneğin:

// defining_namespace_members.cpp
// C2039 expected
namespace V {
    void f();
}

void V::f() { }        // ok
void V::g() { }        // C2039, g() is not yet a member of V

namespace V {
    void g();
}

Ad alanı üyeleri birden çok üst bilgi dosyası arasında bildirildiğinde ve bu üst bilgileri doğru sırada eklemediğinizde bu hata oluşabilir.

Genel ad alanı

Tanımlayıcı açık bir ad alanında bildirilmezse örtük genel ad alanının bir parçasıdır. Genel olarak, genel ad alanında olması gereken giriş noktası main İşlevi dışında mümkün olduğunda genel kapsamda bildirim yapmaktan kaçınmaya çalışın. Genel tanımlayıcıyı açıkça nitelemek için, içinde olduğu gibi ::SomeFunction(x);adsız kapsam çözümleme işlecini kullanın. Bu, tanımlayıcıyı başka bir ad alanında aynı ada sahip her şeyden ayırt eder ve kodunuzun başkalarının anlamasını kolaylaştırmaya da yardımcı olur.

std ad alanı

Tüm C++ standart kitaplık türleri ve işlevleri, içinde stdiç içe yerleştirilmiş ad alanında veya ad alanında bildirilirstd.

İç içe ad alanları

Ad alanları iç içe yerleştirilmiş olabilir. Normal bir iç içe yerleştirilmiş ad alanının üst üyelerine nitelenmemiş erişimi vardır, ancak üst üyelerin iç içe ad alanına (satır içi olarak bildirilmediği sürece) aşağıdaki örnekte gösterildiği gibi nitelenmemiş erişimi yoktur:

namespace ContosoDataServer
{
    void Foo();

    namespace Details
    {
        int CountImpl;
        void Ban() { return Foo(); }
    }

    int Bar(){...};
    int Baz(int i) { return Details::CountImpl; }
}

Normal iç içe yerleştirilmiş ad alanları, üst ad alanının ortak arabiriminin parçası olmayan iç uygulama ayrıntılarını kapsüllemek için kullanılabilir.

Satır içi ad alanları (C++11)

Sıradan bir iç içe ad alanının aksine, satır içi ad alanının üyeleri üst ad alanının üyeleri olarak kabul edilir. Bu özellik, aşırı yüklenmiş işlevlerde bağımsız değişkene bağımlı aramanın bir üst ve iç içe satır içi ad alanında aşırı yükleri olan işlevler üzerinde çalışmasını sağlar. Ayrıca, satır içi ad alanında bildirilen bir şablon için üst ad alanında bir özelleştirme bildirmenizi sağlar. Aşağıdaki örnek, dış kodun varsayılan olarak satır içi ad alanına nasıl bağlandığını gösterir:

// Header.h
#include <string>

namespace Test
{
    namespace old_ns
    {
        std::string Func() { return std::string("Hello from old"); }
    }

    inline namespace new_ns
    {
        std::string Func() { return std::string("Hello from new"); }
    }
}

// main.cpp
#include "header.h"
#include <string>
#include <iostream>

int main()
{
    using namespace Test;
    using namespace std;

    string s = Func();
    std::cout << s << std::endl; // "Hello from new"
    return 0;
}

Aşağıdaki örnek, satır içi ad alanında bildirilen bir şablonun üst öğesinde nasıl özelleştirme bildirebileceğinizi gösterir:

namespace Parent
{
    inline namespace new_ns
    {
         template <typename T>
         struct C
         {
             T member;
         };
    }
     template<>
     class C<int> {};
}

Bir kitaplığın ortak arabiriminde yapılan değişiklikleri yönetmek için sürüm oluşturma mekanizması olarak satır içi ad alanlarını kullanabilirsiniz. Örneğin, tek bir üst ad alanı oluşturabilir ve arabirimin her sürümünü üst ad alanında iç içe yerleştirilmiş kendi ad alanında kapsülleyebilirsiniz. En son veya tercih edilen sürümü barındıran ad alanı satır içi olarak nitelenir ve bu nedenle üst ad alanının doğrudan bir üyesiymiş gibi kullanıma sunulur. Parent::Class öğesini çağıran istemci kodu otomatik olarak yeni koda bağlanır. Eski sürümü kullanmayı tercih eden istemciler, bu koda sahip iç içe yerleştirilmiş ad alanının tam yolunu kullanarak bu sürüme erişmeye devam edebilir.

Satır içi anahtar sözcüğü, bir derleme birimindeki ad alanının ilk bildirimine uygulanmalıdır.

Aşağıdaki örnekte, bir arabirimin her biri iç içe bir ad alanında olmak üzere iki sürümü gösterilmektedir. Ad v_20 alanı, arabirimden v_10 bazı değişikliklere sahiptir ve satır içi olarak işaretlenir. Yeni kitaplığı ve çağrıları Contoso::Funcs::Add kullanan istemci kodu v_20 sürümünü çağırır. Çağırmaya Contoso::Funcs::Divide çalışan kod artık bir derleme zamanı hatası alır. Bu işleve gerçekten ihtiyaçları varsa, açıkça çağırarak Contoso::v_10::Funcs::Dividesürüme erişmeye v_10 devam edebilir.

namespace Contoso
{
    namespace v_10
    {
        template <typename T>
        class Funcs
        {
        public:
            Funcs(void);
            T Add(T a, T b);
            T Subtract(T a, T b);
            T Multiply(T a, T b);
            T Divide(T a, T b);
        };
    }

    inline namespace v_20
    {
        template <typename T>
        class Funcs
        {
        public:
            Funcs(void);
            T Add(T a, T b);
            T Subtract(T a, T b);
            T Multiply(T a, T b);
            std::vector<double> Log(double);
            T Accumulate(std::vector<T> nums);
        };
    }
}

Ad alanı diğer adları

Ad alanı adlarının benzersiz olması gerekir, bu da çoğu zaman çok kısa olmaması gerektiği anlamına gelir. Bir adın uzunluğu kodun okunmasını zorlaştırıyorsa veya kullanma yönergelerinin kullanılamadığı bir üst bilgi dosyasına yazmak yorucuysa, gerçek ad için kısaltma görevi görecek bir ad alanı diğer adı oluşturabilirsiniz. Örneğin:

namespace a_very_long_namespace_name { class Foo {}; }
namespace AVLNN = a_very_long_namespace_name;
void Bar(AVLNN::Foo foo){ }

anonim veya adsız ad alanları

Açık bir ad alanı oluşturabilir, ancak ad veremezsiniz:

namespace
{
    int MyFunc(){}
}

Bu adsız veya anonim ad alanı olarak adlandırılır ve adlandırılmış ad alanı oluşturmak zorunda kalmadan değişken bildirimlerini diğer dosyalardaki kodlarda görünmez hale getirmek istediğinizde (yani iç bağlantı vermek) yararlı olur. Aynı dosyadaki tüm kodlar adsız bir ad alanında tanımlayıcıları görebilir, ancak ad alanının kendisi ile birlikte tanımlayıcılar bu dosyanın dışında veya çeviri biriminin dışında görünür değildir.

Ayrıca bkz.

Bildirimler ve Tanımlar