Программирование >>  Инициализация объектов класса, структура 

1 ... 119 120 121 [ 122 ] 123 124 125 ... 395


#include <iostream> #include <string>

это должно бы находиться в заголовочном файле int lexicoCompare( const string &, const string & int sizeCompare( const string &, const string & ); typedef int (*PFI)( const string &, const string & ); void sort( string *, string *, PFI=lexicoCompare );

string as[10] = { a , light , drizzle , was , falling , when , they , left , the , museum };

int main() {

вызов sort() с значением по умолчанию параметра compare sort( as, as + sizeof(as)/sizeof(as[0]) - 1 );

выводим результат

for ( int i = 0; i < sizeof(as)/sizeof(as[0]); ++i )

сортировки

or ( int i = 0; i < sizeof(as)/s cout << as[ i ].cstr() << \

i ].c str() << \n\t ;

Вот как выглядит main() , в которой применяется наша функция сортировки:

Результат работы программы:


Параметр функции автоматически приводится к типу указателя на функцию:

elem (строка 6) является разделяющим элементом. Все элемент:, меньшие чем elem, перемещаются влево от него, а большие - вправо. Теперь массив разбит на две части. sort() рекурсивно вызывается для каждой из них (строки 20-21).

Цикл for(;;) проводит разделение (строки 10-17). На каждой итерации цикла индекс low увеличивается до первого элемента, большего или равного elem (строка 11). Аналогично high уменьшается до последнего элемента, меньшего или равного elem (строка 12). Когда low становится равным или большим high, мы выходим из цикла, в противном случае нужно поменять местами значения элементов и начать новую итерацию (строки 14-16). Хотя элементы разделен:, elem все еще остается первым в массиве. swap() в строке 19 ставит его на место до рекурсивного вызова sort() для двух частей массива.

Сравнение производится вызовом функции, на которую указывает compare (строки 1112). Чтобы поменять элементы массива местами, используется операция swap() с аргументами тина string, представленная в разделе 6.11.



typedef представляет собой тип функции

typedef int functype( const string &, const string & );

void sort( string *, string *, functype );

void sort( string *, string *,

sort() рассматривается компилятором как объявленная в виде

int (*)( const string &, const string & ) );

Два этих объявления sort() эквивалентны.

Заметим, что, помимо использования в качестве параметра, указатель на функцию может быть еще и типом возвращаемого значения. Например:

int (*ff( int ))( int*, int );

ff() объявляется как функция, имеющая один параметр типа int и возвращающая указатель на функцию типа

int (*)( int*, int ); И здесь использование директивы typedef делает объявление понятнее. Объявив PF с

Использование директивы typedef делает объявления более понятными typedef int (*PF)( int*, int );

помощью typedef, мы видим, что ff() возвращает указатель на функцию:

PF ff( int );

Типом возвращаемого значения функции не может быть тип функции. В этом случае

typedef представляет собой тип функции typedef int func( int*, int );

выдается ошибка компиляции. Например, нельзя объявить ff() таким образом:

func ff( int ); ошибка: тип возврата ff() - функция

7.9.6. Указатели на функции, объявленные как extern

Можно объявлять указатели на функции, написанные на других языках программирования. Это делается с помощью директивы связывания. Например, указатель pf ссылается на С-функцию:

extern C void (*pf)(int);



extern C void exit(int);

pf сс1лается на C-функцию exit() extern C void (*pf)(int) = exit; int main() {

...

вызов С-функции, а именно exit() (*pf)(99);

Через pf вызывается функция, написанная на языке С.

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

void (*pfl)(int);

extern C void (*pf2)(int);

i nt тя i n П i

int main() {

pfl = pf2; ошибка: pfl и pf2 имеют разные типы

...

вызывает ошибку компиляции:

Отметим, что в некоторых реализациях С++ характеристики указателей на функции С и С++ одинаковы. Отдельные компиляторы могут допустить подобное присваивание, рассматривая это как расширение языка.

Если директива связывания применяется к объявлению, она затрагивает все функции, участвующие в данном объявлении.

В следующем примере параметр pfParm также служит указателем на С-функцию. Директива связывания применяется к объявлению функции, к которой этот параметр

pfParm - указатель на С-функцию относится:

extern C void f1( void(*pfParm)(int) );

Следовательно, f1() является С-функцией с одним параметром - указателем на С-функцию. Значит, нередаваем1й ей аргумент должен быть либо такой же функцией, либо указателем на нее, поскольку считается, что указатели на функции, написанные на разных языках, имеют разные типы. (Снова заметим, что в тех реализациях С++, где указатели на функции С и С++ имеют одинаковые характеристики, компилятор может поддерживать расширение языка, позволяющее не различать эти два типа указателей.)

Коль скоро директива связывания относится ко всем функциям в объявлении, то как же объявить функцию С++, имеющую в качестве параметра указатель на С-функцию? С помощью директивы typedef. Например:



1 ... 119 120 121 [ 122 ] 123 124 125 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика