Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org
В этой статье вкратце описыватся , чем С++ отличается от С.

CONST

В чистом C константы определяются с использованием макроса #define . Пример :
 	#define PI 3.14159265358979323846
В С++ добавлена возможность определения константы с помощью ключевого слова const . Пример :
 	const double PI = 3.14159265358979323846;
Значение типа const не может быть изменено. Если указатель на обьект имеет тип const , этот обьект также не может быть изменен :
 	int i = 10;
 	const int *pi = &i;
 	*pi = 15;// Not allowed! pi is a const pointer!
Хотя нет ничего невозможного - данный обьект все же можно поменять с помощью кастинга :
 	// Cast away the constness of the pi pointer and  modify i 
 	*((int*) pi) = 15;

Inline

Макрос #define часто используется в чистом С для определения функций с целью избегать оверхеда для ускорения вызова и скорости ее работы . В С++ для теж же целей можно использовать ключевое слово inline - при этом компилятор С++ разместит код inline-функции раньше , чем код , который ее вызывает . Например :
 	#define max (x, y) ((x)>(y)?(x):(y))
 
 	inline int max (int x, int y)
 	{
 	return (x > y ? x : y);
 	}
Если при определении класса его член функция определяется внутри его тела , она по умолчанию становится inline :
 	class A {
 	int a;
 	 
 	public:
 		A() { }
 		// inline
 		int Value()
 		{
 		return a;
 		}
 		// inline
 	}

Ссылки

Ссылка похожа на указатель . Она должна быть проинициализирована перед использованием .
 	int n = 10;
 	int& r= n;
r теперь является псевдонимом n. В чистом С для модификации параметров вызываемой функции используется механизм call-by-value:
 		void Swap (int* a, int* b) 
 		{
 			int tmp;
 			tmp = *a; 
 			*a = *b;
 			*b = tmp;
 		}
 		int x = 1;
 		int y = 2;
 		Swap (&x, &y);
В C++ для этой цели можно использовать механизм call-by-reference.
 	void Swap (int& a, int& b) 
 	{ 
 		int tmp;
 		tmp = a;
 		a = b;
 		b = tmp;
 	}
 
 	int x = 1;
 	int y = 2;
 	Swap (x, y);

Декларирование

В C++ программах декларация может быть размещена где угодно . Например , поиск ключа в связанном списке :
 	int IsMember (const int key)
 	{
 		int found = 0;
 		if (NotEmpty()) 
 		{ 
 			List* ptr = head;
 			// Declaration 
 
 			while (ptr && !found) 
 			{ 
 				int item = ptr->data;
 				// Declaration 
 
 				ptr = ptr->next;
 				
 				if (item == key) 
 					found = 1;
 			} 
 		} 
 		return found;
 	}	

Расширенная типизация

Произвольный тип , определенный пользователем , может быть создан с помощью классов. Такой тип ведет себя аналогично стандартным типам: int, char, float, double. Например с помощью типа Vector можно выполнять операции сложения и умножения так же легко , как и с типом int :
 	// Define some arrays of doubles 
 	double a[3] = { 11, 12, 13 }; 
 	double b[3] = { 21, 22, 23 };
 
 	// Initialize vectors from the
 	// double arrays 
 	Vector v1 = a; 
 	Vector v2 = b;
 
 	// Add the two matrices. 
 	Vector v3 = v1 + v2;
Можно сконвертировать тип Vector в тип double:
 	double norm = (double) v3;

Перегрузка

Одной из сильных сторон C++ является его способность перегружать функции и операторы. Она позволяет иметь несколько различных фунций с одним и тем же названием. Они будут отличаться числом и типом аргументов. Например , нужно реализовать функцию для работы с массивами разных типов :
 		int Search (
 		const int* data, 
 		const int key);
 
 	int Search (
 		const float* data, 
 		const float key);
 
 	int Search (
 		const double* data, 
 		const double key);
Перегрузка позволяет выполнять операции , на первый взгляд недопустимые :
 	int i = 1;
 	char c = 'a';
 	float f = -1.0;
 	double d = 100.0;
 	int result = i + c + f + d;	

Выделение памяти

В чистом С выделение и освобождение памяти выполняется с помощью malloc и free. В С++ это делается с помощью new delete.
 	int *pi;
 	pi = new int;
 	*pi = 1;
Выделение памяти для массива :
 	int *array = new int [10];
 	for (int i=0;i < 10; i++) 
 		array[i] = i;
Определим тип complex:
 	complex* pc = new complex (1, 2);
 	delete pc;	
Для удаления обьекта надо использовать префикс :
 	delete [] array;	

Инкапсуляция

Так же как структуры в чистом С , в C++ класс - это тип данных Пример:
 	Vector v1(1,2), 
 	Vector v2(2,3), 
 	Vector vr;
 	vr = v1 + v2;
Vector - это класс. v1, v2, vr обьекты класса Vector. Мы добавим несколько перегруженных операторов:
 	Vector v1, v2, vr;
 	add_vector( &vr , &v1, &v2 );
Рассмотрим пример реализации Vector :
 	#include <iostream.h>
 	class Vector
 	{ 
 	public: 
 		Vector(double new_x=0.0,double new_y=0.0) 	{ 
 			if ((new_x<100.0) && (new_y<100.0)) 
 			{	
 				x=new_x;
 				y=new_y;
 			} 
 			else 
 			{ 
 				x=0;
 				y=0;
 			} 
 		}
 		Vector operator + 
 			( const Vector & v) 
 		{ 
 			return
 			(Vector (x + v.x, y + v.y));
 		}
 		void PrintOn (ostream& os) 
 		{ 
 			os << "[" 
 				<< x 
 				<< ", "
 				<< y 
 				<< "]";
 		}
 	 
 	private: 
 		double x, y;
 	};
 
 	int main()
 	{ 
 		Vector v1, v2, v3(0.0,0.0);
 		v1=Vector(1.1,2.2);
 		v2=Vector(1.1,2.2);
 		v3=v1+v2;
 		cout << "v1 is ";
 		v1.PrintOn (cout);
 		cout << endl;
 		cout << "v2 is ";
 		v2.PrintOn (cout);
 		cout << endl;
 		cout << "v3 is ";
 		v3.PrintOn (cout);
 		cout << endl;
 	}
Инкапсуляция x и y означает , что они могут быть изменены только изнутри класса его членами-функциями.

Обработка ошибок

В отличие от чистого C, в C++ имеется встроенный механизм обработки ошибок , который называется exception handling. Если в функции возникает ошибка , она возвращается через исключение - "throw an exception." Рассмотрим пример :
   #include 
 
   int divide(int divisor, int dividend) throw (const char*);
   // Divides divisor with dividend.
   // Precondition, dividend != 0
 
   int main(void)
   {
     try {
       int result = divide(50,2);
       cout << "divide(" << 50 << ", " << 2
            << ") yields " << result << endl;
       result = divide(50,0);
       cout << "divide(" << 50 << ", " << 0
            << ") yields " << result << endl;
     }
     catch (const char* msg) {
       cout << "Oops, caught: " << msg << endl;
     }
     return 0;
   }
 
   int divide(int divisor, int dividend) throw (const char*)
   {
     if (dividend == 0)
       throw (const char*)"Division by zero attempted";
 
     // Here we don't have to worry about dividend being zero
 
     return divisor/dividend;
   }
К прототипу функции добавляется спецификатор "throw (const char*)". В случае деления на 0 вернется будет распечатано сообщение . Критический блок кода нужно заключать в "try/catch" - блок.

Шаблоны

В C++ шаблоны используются для создания функций или классов , которые имеют в качестве параметра определенный пользователем тип. При компиляции будет создана группа таких функций или классов , которая будет оперировать различными типами . Пример:
 	int Max (int x, int y)
 		{ return x > y ? x : y; }
Эта функция имеет 2 целочисленных аргумента и один из них и возвращает. Если нам нужно вычислить максимум из 2-х чисел типа double , прийдется писать другую функцию. С использованием шаблонов это можно сделать так :
 	template <class T>
 	T Max (T x, T y)
 		{ return x > y ? x : y; }
 	int i = Max (1, 2);
 	double d = Max (1.0, 2.0);
Этот шаблон задает семейство функций Max , каждую со своим типом T. Шаблон можно использовать для создания шаблонов-классов :
 	class Stack
 	{
 		// ...
 	public:
 		void Push (int);
 		int Pop ();
 	};
Шаблон с этим классом :
 template < class T>
 	class Stack
 	{
 		// ...
 	public:
 		void Push (T);
 		T Pop ();
 	};
 template < class T>
 	void Stack::Push (T arg)
 	{
 		// ...
 	}
 template < class T>
 	void Stack::Pop ()
 	{
 		// ...
 	}
 
 Stack<int> s1;
 s1.Push (1);
 Stack<double> s2;
 s2.Push (1.0);

Обьектно-ориентированное программирование на C++

OOP - одна из важнейших комплексных технологий программирования. Один из основных постулатов программирования можно сформулировать так : программа - это последовательность инструкций , выполняемых компьютером. В любом обьектно-ориентированном языке основные усилия направлены на создание обьектов и манипуляции с ними. Все примеры этой статьи собраны с помощью GNU C++ компилятора . Для компиляции нужно набрать в командной строке
 	g++ <filename>
Дополнительную документацию о С++ можно найти на http://www.programmingtutorials.com/. Создадим обьект , который будет моделировать реальный дом , с помощью класса :
 	class house
 	{
 	public:
 		int number, rooms; 
 		bool garden;
 	};
 
 	main()
 	{
 		house my_house;
 		my_house.number=40; 
 		my_house.rooms=8;
 		my_house.garden=1;
 		return 0;
 	}
В классе декларируются несколько public-членов. Далее мы декларируем новый тип данных - my_house типа house . Этот тип имеет несколько атрибутов или членов , которые мы определяем . Кроме членов-данных , классы могут иметь члены-функции.
 	class square
 	{
 	public:
 		int length, width;
 		int area()
 		{
 			return length*width;
 		}
 	};
 	main()
 	{
 		square my_square;
 		my_square.length=5;
 		my_square.width=2;
 		cout<<my_square.area();
 		return 0;
 	}
Этот пример выводит число 10 . Код функции-члена можно вынести за пределы класса :
 	class square
 	{
 	public:
 		int length, width;
 		int area();
 	};
 	int square::area()
 	{
 		return length*width;
 	}
Результат будет тем же самым. Теперь несколько слов о разнице между public и private членах . Если член класса определен с ключевым словом public , он доступен из любого места программы . Напишем другую версию класса square :
 	class square
 	{
 	private:
 		int length, width;
 		int area();
 	};
  Теперь мы не сможем записать :
 	main()
 	{
 		sqaure my_square;
 		my_square.length=2;
 		cout<<my_square.length;
 		return 0;
 	}
т.к. доступ к private-членам снаружи запрещен , и компилятор выдаст ошибку . Доступ к таким членам возможен только из других функций-членов , определенных внутри данного класса .

Конструкторы

Конструктор - это функция , которая инициализируется при создании обьекта класса :
 	class square
 	{
 	public:
 		int length, width;
 		square(int length1, int width1)
 		{
 			length=length1;
 			width=width1;
 		}
 		int area()
 		{
 			return length*width;
 		}
 	};
 
 	main()
 	{
 		square my_square(5, 2);
 		cout<<my_square.area();
 		return 0;
 	}
Формально конструктор - это функция , имеющая то же название , что и сам класс.

Массивы и классы

Как с любым типом , с классом можно обращаться как с массивом :
 	class person
 	{
 	public:
 		int age, house_number;
 	};
 
 	main()
 	{
 		person alex[5];
 		for(int x(0); x<5; x++)
 		{
 			alex[x].age=x;
 			alex[x].house_number=x;
 			cout<<"Age is "<<alex[x].age<<endl
 				<<"House number is "<<alex[x].house_number<<endl;
 		}
 		return 0;
 	}
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье
3xe
  Что-то не пойму, ты пытаешься показать, чем C++ "отличается" от C???
2006-01-20 14:41:15
Яковлев Се�
  Это не я пытаюсь
Это перевод чьей-то статьи - щас и не упомню , чьей
Что-то не так ?
2006-01-20 18:40:40
Gad_Polzuch1
  хорошая статья!
2007-01-29 09:11:33
Тимур
  Краткость - сестра таланта
2007-11-23 09:57:01