понедельник, 17 мая 2010 г.

C++ и указатели на...

С++ необъятен. На нем можно порой такие конструкции написать, что не сразу поймешь в чем тут дело. Хотелось затронуть тему указателей. Опытные программисты знают подобные конструкции, поэтому будет больше полезно для сведения (но не для использования) начинающим и продолжающим.

Начнем от простого к сложному.
char *ch; // указатель на символьный тип
int (*arrayPointer)[10];    // указатель на массив из 10-ти целых.
float *pointersArray[10];      // массив из 10-ти указателей на float.

int Foo();         // Функция, возвращающая целое.
double *Foo();  // Функция, возвращающая указатель на double .
int (*Foo())[10];  // Функция, возвращающая указатель на массив из 10-ти целых.

int (*ptrFoo)();      // Указатель на функцию, возвращающую целое.
float *(*ptrFoo)();   // Указатель  на функцию, возвращающую  указатель на float .
char (*ptrFoo[10])(); // Массив из 10-ти указателей на функции, возвращающие char.

double (*Foo())(); // Функция, возвращающая указатель на функцию, возвращающую double
Из приведенных прототипов можно понять правило формирования указателей на что-либо.

Cоздадим указатель на функцию, возвращающую указатель на массив из 10-ти указателей на функции, принимающие в качестве параметра указатель на float, и возвращающие указатель на double.

Сперва создадим указатель:
*Foo; // Или обозначим это буквой A
Сделаем его указателем на функцию:
(*Foo)(); // Или (A)(), данное выражение обозначим как B
Сделаем чтобы данная функция возвращала просто указатель, пока ни на что:
*(*Foo)(); // Или *B, данное выражение обозначим как С
Теперь уточним, что требуется указатель на массив из 10-ти элементов:
(*(*Foo)())[10]; // или (C)[10]
Уточним что элементы массива должны быть указателями:
*(*(*Foo)())[10]; // или *(C)[10], данное выражение обозначим как D
И не просто указателями, а указателями на функции:
(*(*(*Foo)())[10])(); // или (D)()
Притом, функции эти должны возвращать double-значение и принимать float*:
double (*(*(*Foo)())[10])(float*); // или double (D)(float*)
Если же мы хотим, чтобы вместо double-значения возвращался указатель на функцию, возвращающую double-значние, просто добавим скобок:
/* вместо double* - дополнительно (* и  //соотвественно, закрывающуюся скобку + '()' */
double (* (*(*(*Foo)())[10])(float*) )();

На практике такие конструкции применять... не надо, ибо очень экзотичны и легко запутаться. Здесь они просто для справки