beesoft.org

STL. Przestrzen nazw.

Coraz wiekszym problemem staje sie nadawanie nazw klasom, funkcjom czy zmiennym.
Rozrastania sie programow powoduje coraz to wieksze zapotrzebowanie na kolejne nazwy. W ramach wlasnego projektu, mozna ten problem ewentualnie ominac. Ale tak sie sklada, ze coraz czesciej oprogramowanie dystrybuowane jest w formie bibliotek. A na zastosowany w nich system nazewniczy niestety nie mamy zadnego wplywu. Jesli stosujemy jakas biblioteke (np. STL), bardzo latwo moze dojsc do konfliktow z nazwami, ktore sami wymyslelismy piszac program. Jezeli dodatkowo sie okaze, ze musimy uzywac wiekszej liczby bibliotek, ktore wykorzystuja takie same nazwy, to mamy powazny problem.

Zadaniem przestrzeni nazw jest wprowadzenie logicznego rozdzialu pomiedzy oprogramowaniem otrzymywanym z roznych zrodel.
Rozwazmy sytuacje, gdy dwie firmy tworza swoje biblioteki, i obie zamierzaja wykorzystywac wlasne klasy CWidget i CViewer. Oczywiscie w normalnej sytuacji bedziemy mieli problem ze zlinkowaniem obu bibliotek razem z naszym programem. Linker nie dopuszcza dwoch identyfikatorow o takich samych nazwach. Wlasnie przestrzen nazw pozwala w sposob prosty i elegancki rozwiazac ten problem.

Pierwsza firma powinna zdeklarować swoje klasy w swojej przestrzeni nazw:

namespace FirmaA
{
	class CWidget();
	class CViewer);
};
A druga w swojej:
namespace FirmaB
{
	class CWidget();
	class CViewer);
};
I po problemie.

Od tej chwili, klasy CWidget i CViewer z FirmyA kompilator i linker bedzie tak na prawde widzial jako FirmaA::CWidget i FirmaA::CViewer.
Z klasami drugiej firmy bedzie podobnie.

Dowcip polega na tym, ze nawet jesli w swoim programie nie deklarujemy jakiejs wlasnej przestrzeni nazw, to i tak ja mamy i uzywamy. Jesli uzytkownik nie zadeklaruje explicite swojej przestrzeni nazw, to kompilator deklaruje domyslna tzw. nienazwana przestrzen nazw.

Biblioteka STL ma zadeklarowane wszystkie swoje skladniki w przestrzeni nazw std.
Oznacza to, ze dostep do jej skladowych mozna uzyskac w nastepujacy sposob:

#include <vector>
#include <string>
...
...
std::vector<int> numbers;
std::string path_to_file;
...
numbers.push_back( 5 );
path_to_file.find_first_of( '/' );

Oczywiscie, ciagle pisanie 'std::' jest uciazliwe. Mozna dana przestrzen nazw uczynic domyslna.
Do tego celu sluzy instrukcja 'using namespace'.
Jesli wpiszemy:

#include <vector>
#include <string>
using namespace std;
to od tej chwili nie musimy za kazdym razem pisac 'std:', piszemy po prostu:
vector<int> numbers;
string path_to_file;

Uzycie using namespace powoduje 'otwarcie' przestrzeni nazw.
Otwarcie w zakresie jednostki translacji(!), w ktorej tego dokonano. Dlatego using namespace uzywamy TYLKO I WYLACZNIE w pliku 'cpp'. Nigdy w pliku naglowkowym. W kazdym pliku 'cpp' musimy wprost dokonac 'otwarcia' przestrzeni nazw przez uzycie using namespace. W plikach naglowkowych zawsze stosujemy pelne okreslenie funkcji czy klasy:

// CWidget.h
#include <string>
...
class CWidget
{
....
private:
	std::string name_of_widget;
};

I ostania uwaga: otwarcie przestrzeni nazw nie ma sensu, gdy uzywamy wiekszej liczby bibliotek. Moze to doprowadzić do konfliktu nazw, ktorego chcielismy uniknac. W takiej sytuacji pozostaje nam uzywanie pelnej nazwy klasy czy funkcji, razem z okreslnikiem przestrzeni nazw.

Contact: piotr@beesoft.org
(C) 2006-2008 beesoft.org
Last modification date: 2008-06-29
Visitis counter:
counter of visits