C, PHP, VB, .NET

Дневникът на Филип Петров


* Namespace конструкции и нов стил header файлове

Публикувано на 28 ноември 2008 в раздел С/С++.

Namespace е конструкция за езика C++, която представлява разширение на познатите досега класове, а именно – един namespace може да съдържа в себе си набори от класове. По този начин от една страна се получава естествено обединение на обектите, които имат сходна функционалност, а от друга се решава един основен проблем в дизайна на програмите. Представете си, че имате два header файла, които искате да използвате:

	#include "header1.h"
	#include "header2.h"

Нека обаче в тези файлове се съдържат класове с повтарящи се имена:

	// header1.h
	class myClass {
		...
	};
	...

	// header2.h
	class myClass {
		...
	};
	...

В такъв случай моментално в нашата програма ще се получи конфликт, понеже ще се опитаме да дефинираме myClass два пъти. Този проблем се решава, като използваме namespace конструкцията:

	// header1.h
	namespace header1 {
		class myClass {
			...
		};
	}

	// header2.h
	namespace header2 {
		class myClass {
			...
		};
	}

Когато искаме да използваме така създадените header файлове ние имаме два метода за работа с класовете в тях. Първият начин е да се извикват директно, чрез указване на namespace:

	main(){
		...
		header1::myClass a;
		header2::myClass *d = new header1::myClass;
		...
	}

Друг начин е да използваме ключовата дума “using” за един от класовете:

	main(){
		...
		using namespace header1;
		myClass a; // a ще е от класа в header1
		header2::myClass *d = new header2::myClass;
		...
	}

Имайте предвид, че ако укажете “using namespace header1″ и “using namespace header2″ отново ще се появи споменатият преди това конфликт. Затова при използване на namespace се препоръчва да се използва операторът “::”. Ако дефинирате namespace, който няма име, то той по подразбиране ще бъде включен чрез ключовата дума “using” от компилаторът.

Интересна и често използвана при писане на библиотеки възможност са вложени namespace:

	namespace root
	{
		class A{
		public:
			int var1;
		};

		namespace sub
		{
  			class A{
			public:
				int var2;
			};
		}
	}

	int main () {
		root::A a;
		a.var1 = 5;

		root::sub::A b;
		b.var2 = 6;

		return 0;
	}

Най-често използвания и най-популярен namespace е “std”. Принципно “C++ Standards Committee” са пренаписали напълно стандартната библиотека на C++, като са сложили най-често използваните стандартизирани обекти в този namespace.

Друго много важно обновяване на езика е въвеждането на нов стил header файлове. Досега не сме ги разглеждали, понеже целяхме да имаме максимална съвместимост за програми писани на С и стари компилатори. В кода на програмата всъщност няма особена разлика – просто не се добавя “.h” в името на файла при include:

	Стар стил:
	#include "iostream.h"
	#include "fstream.h"
	#include "string.h"
	#include "math.h"
	#include "stdlib.h"

	Нов стил:
	#include <iostream>
	#include <fstream>
	#include <string>
	#include <math>
	#include <cstdlib>

Въпреки, че имат известни разлики в имплементацията (например fstream.h добавя iostream.h автоматично, а fstream не; string.h използва С-стил низове, а string използва обектни низове; r тн) главната функционалност и най-често използваните функции остават същите. Препоръчително е при писането на програми за нови компилатори да използвате новата конвенция. Нещата, които трябва да запомните са:
1. Никога не “миксирайте”, като вкарвате библиотеки от стар и нов стил едновременно.
2. Ако компилаторът поддържа новите библиотеки, то е добре да използвате тях, тъй като се счита, че функционалността и надеждността при тях е подобрена.
3. Не е изключено в близко бъдеще новите компилатори да не поддържат старите библиотеки.
4. Ако искате да използвате namespace std, то трябва да добавите поне една от новите библиотеки.

По принцип всички функции в новите стандартни библиотеки използват namespace std. Следният пример демонстрира това, като в допълнение показва още една новост за миксиране на глобални и локални променливи с едно и също име:

	#include "stdafx.h"
	#include <iostream>
	// Глобална променлива
	int var = 5;

	void main(){
		// Локална променлива
		int var = 10;
		// Отпечатваме локалната променлива
		std::cout << var << std::endl;
		// Отпечатваме глобалната променлива
		std::cout << ::var << std::endl;
		// Добавяме namespace std
		using namespace std;
		// Вече може да използваме cout директно
		cout << "Hello world" << endl;
	}

Забележете, че ако не сме добавили “using namespace std” при новия стил функции, то програмата няма да разпознае функциите ако не ги извикаме чрез “std::”.

 



2 коментара


  1. Тодор Желев Желев каза:

    Ако разполагаме с външна библиотека от функции,как могат да се използват.Къде се поместват в дисковото пространство файловете?Изобщо,кой раздел от C++ дава отговор на този въпрос?

  2. Правиш include и името на файла, а после при компилиране добавяш като параметър директорията, в която го има. При g++ това е -I (include) и -L (lib).

    Иначе всяка визуална среда има възможност за добавяне на външна библиотека.

Добави коментар

Адресът на електронната поща няма да се публикува


*