Пространства от имена.

Пространства от имена.

Namespace

Пространствата са допълнение към езика С++. Една програма включва много идентификатори, които са с различна област на действие. Понякога идентификатор от една област на действие може да бъде дублиран с идентификатор със същото име от друга област на действие. Например, два програмиста пишат различни части на библиотека за работа с числа. Нужен им е клас vector, който да харектеризира числен вектор. Но в C++ STL този клас вече е дефиниран и прави нещо друго. В такива случаи се генерира грешка по време на компилация.

В стандарта на C++ се предлага решение на този проблем с помощта на пространства от имена. Всяко пространство от имена определя област на действие, в която са включени идентификатори, за да се използва елемент от пространството от имена, неговото име трябва да се обяви заедно с името на пространството и бинарната операция за разрешаване на област на действие по следния начин:

име_на_пространство::елемент_на_пространство

Например std::vector или numeric::vector.

using

Възможно е да се избегне посочването на името на пространството при използването на даден елемент. Това се постига чрез оператор using, поставен в началото на блока, в който този елемент се използва. using namespace std; в началото на програмата, например, дава възможност операторите « и », както и стандартната библиотека да се използват без std::. Това е много често използвана библиотека, затова може да бъде прието да се пише using при работа с нея. Но в общия случай, по-добър стил е да се поставя име_на_пространството и :: пред всеки елемент от съответния namespace. Причината за това е, че ако има няколко библиотеки и за всяка от тях се използва using namespace, скоро програмата ще се замърси с твърде много имена на функции, те най-вероятно ще си пречат и поддръжката ще стане трудна. Освен това, при правилно избрани имена, програмирането ще бъде по-интуитивно.
Името на функцията send не е много информативно, но email::send например, звучи по-добре.

Не всички пространства от имена са уникални. Независими разработцичи могат по случайност да използват едно и също пространство.

Пример

Програма демонстрираща използването на пространства от имена:

#include <iostream> // допълнение към стандарта е възможността да пропуснем .h
using namespace std;
 
int myInt = 98;
namespace Numeric_Constants
{
    const double PI = 3,14159;
    const double E = 2,71828;
    int myInt = 8;
    void printValues();
    namespace Date
    {
        enum Years
        {
            FISCAL1 = 1970,
            FISCAL2,
            FISCAL3
        };
    }
}
 
namespace
{
    double d = 88,22;
}

using namespace дава възможност за достъп до всички членове на указаното пространство, тъй като съдържимото на iostream включва част от пространството standard. Отново, лоша практика е използването на using. Тук е приемливо само защото това е стандартното пространство. Без using namespace std всеки cout и endl трябва да се използват като std::cout и str::endl.

При определяне на Numeric_Constants се използва namespace. Тялото му се загражда във фигурни скоби, но за разлика от класа не завършва с ';'. Членове на Numeric_Constants са PI и E, myInt, printValues, namespace Date. myInt се дублира като име. Променливи с еднакви имена трябва да имат различни области на действие. Пространството от имена може да съдъра константи, променливи, функции, класове, вложени пространства. Всъщност, самото пространство не представлява някаква синтактична структура. То не е клас, няма предефинирани оператори и не поставя ограничения.

Единственото приложение на пространството от имена е да разделя програмата на малки и по-удобни за работа части.

Достъп до променливите

void main()
{
    cout <<"d =  "<< d <<endl;                        // 88,22
    cout <<"Външна myInt =  " << myInt <<endl;      // 98
    cout <<"Вътрешна myInt =  " << Numeric_Constants:: myInt <<endl;      // 8
    cout << "PI =  " << Numeric_Constants::PI <<endl;          // 3,14159
    cout << "E =  " << Numeric_Constants::E <<endl;             // 2,71828
    cout << "FISCAL3 " << Numeric_Constants::Inner::FISCAL3 << endl;    //1970
    Example::printValues();
}

PI, E, myInt са членове на Example – заради което се обявяват с Example::, myInt трябва да има Example::, тъй като има външна променлива със същото име, иначе ще се изведе стойността на външната променлива.
FISCAL3 е член на Inner, което е вложено, затова изпозлваме Example::Inner::FISCAL3.
Членове на пространство без име(в случая - d) са част от глобалното пространство на имената. Те са непосредствено достъпни. Външните променливи са също част от глобалното пространство имена и са достъпни във всички области на действие след тяхното дефиниране. Защо някой би искал да прави именовано пространство без име, остава мистерия. (Всъщност не е чак такава мистерия - първо, анонимното пространство от имена е равносилно на спецификатора за достъп static и се вижда и пипа отвсякъде и, второ, винаги стои въпросът дали стремежът на човек да му е по-лесно е изначален или подшушнат от цивилизацията и след като съществуват много начини за постигане на един и същ ефект, може да си позволи да използва най-изкълчения…знаете за какво става дума, особено когато програмират неосъществени тъмни философи, които все таки не желаят да бъдат разбрани…)

void Numeric_Constants::printValues()
{
    cout << "In printValues(): " << endl;
    cout << "myInt =  "<< myInt << endl;
    cout << "PI =  " << PI << endl;
    cout << "E =  " << E << endl;
    cout << "d =  " << d << endl;
    cout << "Вътрешната myInt = "<< myInt <<endl;
    cout << "Външната myInt = "<< ::myInt <<endl;
    cout << "FISCAL3 =  " <<  Inner::FISCAL3 << endl;
    /* И така нататък... */
}

Тъй като самата функция е дефинирана в Numeric_Constants, имаме непосредствен достъп до другите членове на същото пространство (няма нужда от Numeric_Constants::). Членът d все още е достъпен, а външната myInt е обявена с унарната операция ::, а членът FISCAL3 с бинарната Inner::. За достъп до членовете на вложеното пространство от имена е необходимо да бъдат обявени с името на пространството, само ако достъпът не е от вложено пространство.

Правилна употреба на using

Using може също да се използва за непосредствен достъп до отделни членове от пространства на имена, например:

using Example::PI;

Това позволява непосредствен достъп до члена PI на Example. Обикновено се прави това, когато само 1 член от пространството се изпозлва често. Пространствата от имена могат да имат псевдоними, например:

namespace CPPHTP3E = CplusPlusHowToProgram3E;

Например, за да се избегне замърсяване на namespace-а, но и да може да се работи удобно, един компромис би бил:

using std::cin;
using std::cout;
using std::endl;
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License