В этой статье вкратце описыватся , чем С++ отличается от С.
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 | |
|
|