Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Languages
 С
 GNU С Library 
 Qt 
 STL 
 Threads 
 C++ 
 Samples 
 stanford.edu 
 ANSI C
 Libs
 LD
 Socket
 Pusher
 Pipes
 Encryption
 Plugin
 Inter-Process
 Errors
 Deep C Secrets
 C + UNIX
 Linked Lists / Trees
 Asm
 Perl
 Python
 Shell
 Erlang
 Go
 Rust
 Алгоритмы
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Secure Programming for Li...6507 
 Linux Kernel 2.6...5279 
 Trees...1119 
 Максвелл 3...1051 
 William Gropp...990 
 Go Web ...963 
 Ethreal 3...930 
 Ethreal 4...917 
 Gary V.Vaughan-> Libtool...914 
 Ext4 FS...905 
 Clickhouse...901 
 Rodriguez 6...900 
 Ethreal 1...897 
 Steve Pate 1...886 
 C++ Patterns 3...864 
 Assembler...854 
 Ulrich Drepper...844 
 DevFS...788 
 MySQL & PosgreSQL...774 
 Стивенс 9...758 
 
  01.01.2024 : 3621733 посещений 

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