FreeSource: Статьи/КраткоОбоВсём/Clang/part1/part4

1.4 Синтаксис

1.4.1 Полезные обороты

long с = (long)a; - традиционная запись; 

long с = long(a); - функциональная запись;

int x,  // x

    y,  // y

    z;  // z

#ifndef TEST_H

#define TEST_H

<code>

#endif

#if 0

<code>

#endif

void show_values(int one=1, int two=2, int three=3);

show_value();

show_value(23);

for (int count = 0; count < 10;count++)

void text(parm x,char *fmt, ...)

 {

   char str[100];   

   va_start (argptr,fmt);

   vsprintf(str,fmt,argptr);

   va_end(argptr);

   printf(str);

 }

 text(54,"hello %s","world");

extern "C" func();  // В стиле "C"

 extern "C++" func(): // В стиле "C++"

 extern "C++" 

 {

  int func(void);

 }

1.4.2 Указатели

Особенностью языка С/С++ является возможность доступа к переменной не только по имени но и с использованием механизма указателей. Для этого в языке предусмотрены символы: “&" и "*".

Символ "*" используется для индикации переменной (*ptr), которая расположена в памяти по адресу на который указывает одноимённая переменная без звёздочки. Символ “&" используется как для определения адреса ячейки памяти переменной, так и для определения адреса указателя на переменную.

int *ptr = (int *)0x0010;   //при инициализации  

 ptr      = (int *)0x0010;   //в программе

*ptr = 300

unsigned long block = 0xffeeddccL; 

 void *ptr = &block;

 unsigned char = *(unsigned char *)ptr; 

 long int four_bytes = *(long int *)ptr;

int *ptr; 

 k = &ptr;

int data = 5;

 int *ptr = &data;    // ptr[0]==5; 

 int **ptr1 = &ptr;   // ptr1[0][0]==5; 

 int ***ptr2 = &ptr1; // ptr2[0][0][0]==5;

bool *cimpare(int, int);

bool (* compare)(int, int);

class Test

{

  public:

    void funct() { cout << "Функция\n"; }

    int value;

};

Test t;

Test *tPtr = &t;

void (Test::*memPtr)() = &Test::funct;

int  Test::*vPtr = &Test::value;

(tPtr->*memPtr)(); //косвенный вызов функции

cout << (*tPtr).*vPtr << endl;

1.4.3 Ссылки (C++)

Ссылка являются псевдонимом (алиасом) от переменной на которую она ссылается. При изменении ссылаемой переменной изменяется ссылка. В основном ссылки используются при описании параметров функций и указывают что переменная может меняться.

int &test(int &x);

 int data = 5;

 int &al_data = data;    // al_data == 5; 

 al_data = 10;           // data == 10; 

 data = 7;               // al_data == 7;

1.4.4 Массивы

Как и в других языках, С/С++ поддерживает массивы которые тесно переплетаются с указателями. Элементы массива имеют один и тот же тип и расположены в памяти друг за другом. Имя массива также можно воспринимать как указатель на начало массива.

В отличие от других языков в С/С++ отсутствует специальный строковый тип. Вместо него строковые литералы представляются как одномерный массив элементов типа char оканчивающегося символом “0”.

char array[]  = {'A','B','C','D',0};

 char array[]  = "ABCD";

 char array[5] = {'A','B','C','D',0};

 char *string  = "ABCD";

 string        = "ABCD";

*(array+i); 

 array[i][j];    

 *(array[i]+j);  

 *(*(array+i)+j);

matrix[2] == &matrix[2][10]; 

 long (* matrix1)[3][2][4];

 matrix1 = new long[3][2][4];

 char *messages[20] == char messages[20][80]);

 char string[][80]=

 {

   "Первая строка",

   "Вторая строка",

   "Следующая строка"

 }; 

 int m[][3] = { {00}, {10, 11}, {20, 21, 22,} }; 

 char *Names[]= { "Aleksey", "Vladislav", "Vitaly" };

int  (* fcmp[5])(int) =  

 {cmp_name, cmp_title, cmp_year, cmp_price, cmp_totaly};

 void (* func[3])(int);    //определение

 (* func[choice])(choice); //вызов

1.4.5 Перегрузка функций

В языке C++ разрешается иметь множество функций с одним и тем же именем, но отличающиеся типами параметров или их количеством:

int sum(int *array, int element) {   }

 float sum(float *array, int element) {   }

1.4.6 Перегрузка операций

Перегрузкой операция является процедура расширения функций существующих операция для новых типов x(объектов). Операции допускающие перегрузку указанны в табл.4. При перегрузке операций их старшинство и ассоциативность не изменяется.

Операция:! S 

Вызывает: S.operator!() или operator!(S)

Объявляется: bool operator!() const; или friend bool operator!(const String &);

Операция: d1++

Вызывает: d1.operator(0) или operator(d1,0)

Объявляется: Date::operator(int); или friend Date::operator(Date &,int);

Операция: y+=z

Вызывает: y.operator+=(z) или operator+=(y,z)

Объявляется: const String &operator+=(const String &); или friend const String &operator+=(String &, const String &);

Операция: string(2,2);

Вызывает: string.operator()(2,2);

Объявляется: String operator()(int,int);

Операция: (char *)S;

Вызывает: S.operator char*()

Объявляется: String operator char*(); или String(char *); (конструктор неявного преобразования).

Операция: Class1 *cls = new Class1; или Class1 *cls = new («class») Class1;

Вызывает: Class1 *cls = Class2.operator new(sizeof(Class1)); или Class1 *cls = Class2.operator new(«class», sizeof(Class1));

Объявляется: void* Class2::operator new(size_t size); или void* Class2::operator new(string modul, size_t size);

Операция: delete cls;

Вызывает: Class2.operator delete(cls);

Объявляется: void* Class2::operator delete(void *addr);

Таблица 4. Операции допускающие перегрузку

+-*/%^&|
~!=<>+=-=*=
/=%=^=&=|=<<>>>>=
<<===!=<=>=&&||++
--->*,->[]()newdelete
new[]delete[]

1.4.7 Шаблоны

Шаблоны определяются с помощью ключевого слова template и предназначены для определения функций и классов способных работать с различными типами входных и выходных параметров. Шаблоны и наследование связаны следующим образом:

Шаблонные классы:

template <class Templ>

 class Tree 

 {

   public:

     Tree( const Templ& n );

     insertN(const Templ &);

 } 

 template <class Templ>

 Tree<Templ>::Tree(const Templ& n) { };

Tree<int> NewTree(23); 

 Tree<float> NewTree(56.8);

Шаблонные функции:

template <class T> // или template <typname T>;

 T max(T val1, T val2, T val3)

 {

   T max = val1;

   if(val2 > max) max=val2; 

   if(val3 > max) max=val3; 

   return max;

 }

int rez = max(1,10,3);

 float rez = max(0.5,9.99,6.78);

Шаблоны и друзья:

friend void f1();    //друг любого класса

 friend void f2(x<T> &); //друг конкретного класса

 friend void A::f4(); //друг любого класса

 friend void C<T>::f5(x<T> &); //друг конкретного класса

 friend class Y;      //класс Y дружественен любому классу

 friend class Z<T>;   //класс Y дружественен конкретному классу

1.4.8 Обработка исключительных ситуаций

В языке C++, добавлен мощный аппарат обработки исключительных ситуаций. Этот аппарат позволяет отлавливать как все типы исключений, так и конкретно взятый тип исключений. Так если записать catch(...), то будут отлавливаться все типы исключений. Кроме того обработка исключительных ситуаций оказываться вынесенной из «основной линии» выполнения программы. Для генерации повторных исключений в catch опускаться использование (throw) без параметров. Если происходит глубоковложенное исключение, то выполняется «раскрутка» стека для возвращения до ближайшего catch Обработка исключительных ситуаций описывается следующим образом:

try  //начало блока испытания

{

  if() throw MyType();    // Принудительная генерация 

}                         //  (точка генерации)

catch(MyType &Mt) {...}; // Отлов и обработка исключений My Type

catch(...){...}; // Отлов и обработка всех остальных исключений

Для ограничения круга генерируемых исключений функцией, можно указать спецификацию исключений для функции:

int g(double h) throw(a,b,c) //может генер. a,b,c и 

                              //unexpected

 int g(double h) throw()      //не может генерировать

                              //(кроме unexpected)

 int g(double h)              //может генерировать все

Стандартные исключения:

Чтоб избежать утечек памяти, обусловленных забыванием вызова delete после new, можно использовать шаблон auto_ptr, который будет автоматически разрушаться.

На базе класса exception, можно генерировать собственные исключения.