Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Voprosy_k_ekzamenu_OOP.rtf
Скачиваний:
4
Добавлен:
24.09.2019
Размер:
526.36 Кб
Скачать
  1. Начнем с краткого обзора простых указателей на функции. В С, и С++ в частности, указатель на функцию с именем my_func_ptr , указывающий на функцию, принимающую в качестве аргументов int и char*, и возвращающую float, объявляется так:

    1. float (*my_func_ptr)(int, char*);

    2. // Для большей удобочитаемости, я очень рекомендую использовать typedef.

    3. // Особенно можно запутаться, когда указатель на функцию является аргументом

    4. // функции.

    5. // Тогда бы объявление выглядело так:

    6. typedef float (*MyFuncPtrType)(int, char*);

    7. MyFuncPtrType my_func_ptr;

  2. Заметьте, что различным комбинациям аргументов соответствуют различные типы указателей на функцию. В MSVC, кроме этого, указатели на функцию различаются в зависимости от типа соглашения о вызове (calling conventions): __cdecl, __stdcall, __fastcall. Для того чтобы указатель на функции указывал на вашу функцию, необходимо выполнить следующую конструкцию:

    1. my_func_ptr = some_func;

  3. Для вызова функции через указатель:

    1. (*my_func_ptr)(7, "Arbitrary string");

  4. Разрешается приводить один тип указателя на функцию к другому. Но не разрешается приводить указатель на функцию к указателю на void. Остальные разрешенные операции тривиальны. Указателю на функцию можно присвоить 0 для обозначения нулевого указателя. Доступны многочисленные операторы сравнения (==, !=, <, >, <=, >=), можно также проверить на равенство 0 либо неявным преобразованием к bool. Кроме того, указатель на функцию может быть использован в качестве нетипизированного параметра шаблона. Он в корне отличается от типизированного параметра, а также отличается от интегрального нетипизированного параметра шаблона. При инстанцировании используется имя, а не тип или значение. Именные параметры шаблонов поддерживаются не всеми компиляторами, даже не всеми из тех, которые поддерживают частичную специализацию шаблонов.

  5. Наиболее распространенное применение указателей на функции в С – это использование библиотечных функций, таких как qsort, и обратных (callback) функций в Windows. Кроме того, есть еще много вариантов их применения. Реализация указателей на функции проста: это всего лишь «указатели на код», в них содержится начальный адрес участка ассемблерного кода. Различные типы указателей существуют лишь для уверенности в корректности применяемого соглашения о вызове.

                  1. Указатели на функции-члены

  6. В программах на С++, большинство функций являются членами. Это означает, что они являются частью класса. И использовать обычный указатель на функцию в этом случае нельзя. Вместо этого нужно использовать указатель на функцию-член. Указатель на функцию-член класса SomeClass, с теми же аргументами, что и ранее, объявляется следующим образом:

    1. float (SomeClass::*my_memfunc_ptr)(int, char*)

    2. // Для константных функций-членов используется объявление

    3. float (SomeClass::*my_const_memfunc_ptr)(int, char*) const;

  7. Заметьте, что используется специальный оператор ( ::* ), а при объявлении используется класс SomeClass. Указатели на функции-члены имеют очень серьезное ограничение – они могут указывать лишь на функции-члены одного класса. Различным комбинациям аргументов, типам константности и различным классам соответствуют различные указатели на функции-члены. В MSVC , кроме того, указатели различаются по типу соглашения о вызове: __cdecl, __fastcall, __stdcall и __thiscall (__thiscall по умолчанию. Заметим, что документированного квалификатора __thiscall нет, но он иногда появляется в сообщениях об ошибках. Если вы попробуете использовать его явно, то получите сообщение об ошибке, информирующей о том, что использование этого квалификатор зарезервировано для будущих нужд.) При использовании указателей на функции-члены всегда следует использовать typedef, во избежание ошибок и лишних неприятностей.

  8. Чтобы указатель на функцию-член указывал на метод класса SomeClass::some_member_func(int, char*), нужно выполнить следующую инструкцию:

    1. my_memfunc_ptr = &SomeClass::some_member_func;

  9. Многие компиляторы (например, NSVC) разрешат вам пропустить взятие адреса (&), но более соответствующие стандарту (например, GNU G++) потребуют этого. Так что если пишете портируемый код, то не забывайте &. Для вызова метода через указатель на функцию-член нужно предоставить объект SomeClass и воспользоваться специальным оператором (->*). Данный оператор имеет низкий приоритет, так что его следует поместить в скобки:

    1. SomeClass *x = new SomeClass;

    2. (x->*my_memfunc_ptr)(6, "Another arbitrary parameter");

    3. // Также можно использовать оператор .* если класс создан на стеке

    4. SomeClass y;

    5. (y.*my_memfunc_ptr)(15, "Different parameter");

  10. Прошу меня не винить в ужасном синтаксисе – похоже, кто-то из разработчиков С++ любит знаки препинания!

  11. С++ добавил в С три специальных оператора специально для поддержки указателей на функции-члены. ::* используется при объявлении указателя, ->* и .* используются при вызовах методов, на которые указывает указатель. Похоже, очень много внимания было уделено этой неясной и редко используемой части языка (разрешено даже перегрузить оператор ->*, однако, я не представляю, для чего это может вам потребоваться; я только знаю одно применение [Meyers]).

  12. Указатели на функции-члены могут быть установлены в 0, и предоставляют операторы ==, !=, но лишь для указателей на функции-члены одного класса. Любой указатель на функцию-член может быть проверен на равенство 0. В отличие от простых указателей на функции, операции сравнения на неравенство (<,>, <=, >=) недоступны. Как и простые указатели, они могут быть использованы как нетипизированные параметры шаблона.

                  1. 22. Экземпляризация классов и функций из шаблонов. Примеры

                  2. Шаблоны функций и классов

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

  14. Шаблоны функций позволяют передавать в качестве аргумента тип переменной. Шаблоны создают семейства функций, определяющее неограниченное множество родственных функций. Экземпляризация— операция создания определённого типа из шаблона. Отдельные классы называются экземплярами шаблона. Параметризованные шаблоны — представляют возможность создания общего класса  и для построения конкретных экземпляров передают этому классу в качестве параметров типы данных.

  15. На пример список. Список может быть для чего угодно.

  16. Построение шаблонов рассмотрим на примере. Необходимо написать функцию расчёта куба для аргумента. (Cub()).

  17. #include<iostream.h> #include<math.h>

  18. template <class T>    T cub(T x)    {          return x*x*x;} template <class SwapType> void Swap(SwapType &x,SwapType &y) { SwapType tmp;    tmp=x;    x=y;    y=tmp; } template <class T1,class T2> T1 max(T1 x,T2 y) { if(x>y)return x; else return y; } void main(void) {    int i=3;    float f=3.12;    double x=3.1e2;    cout<<"//целое "<<cub(i)<<endl;    cout<<"//вещественное "<<cub(f)<<endl;    cout<<"//двойной точности "<<cub(x)<<endl;    char ch1='a',ch2='z';    cout<<"//1-- "<<ch1<<"  2-- "<<ch2<<endl;    Swap(ch1,ch2); cout<<"//переставили "<<endl;    cout<<"//1-- "<<ch1<<"  2-- "<<ch2<<endl;    int c1=0,c2=9;    cout<<"//1-- "<<c1<<"  2-- "<<c2<<endl;    Swap(c1,c2); cout<<"//переставили "<<endl;    cout<<"//1-- "<<c1<<"  2-- "<<c2<<endl;

  19.    cout<<"//max из  int "<<c1<<" и int "<<c2<<" = "<<max(c1,c2)<<endl;    cout<<"//max из  char "<<ch1<<" и char "<<ch2<<" = "<<max(ch1,ch2)<<endl;    cout<<"//max из  int "<<i<<" и float "<<f<<" = "<<max(f,i)<<endl; }

  20. //целое 27 //вещественное 30.3713 //двойной точности 2.9791e+07 //1-- a  2-- z //переставили //1-- z  2-- a //1-- 0  2-- 9 //переставили //1-- 9  2-- 0 //max из  int 9 и int 0 = 9 //max из  char z и char a = z //max из  int 3 и float 3.12 = 3.12

  21.  

                  1. Шаблоны классов

  22. Шаблон класса представляет собой скелет обобщённого класса. Ситаксис такой:

  23. Template< список_аргументов_шаблона> {              //тело класса };

  24. Каждый аргумент в списке является либо объявлением типа float a; либо идентификатором класса class T. Из-за этого определение функции-метода шаблонного класса имеет вид: Template< список_аргументов_шаблона> Тип_результата имя_класса < список_аргументов_шаблона>:: Имя_функции( список_аргументов_функции) { //тело функции. }

  25. объявление объекта шаблонногокласса: имя_класса_шаблона < список_аргументов_шаблона> имя_объекта; Пример использования шаблонов будем рассматривать на создании очереди.

  26.  

                  1. Связные списки и другие структуры

  27. Для работы с массивом необходимо знать его размерность, хотя бы в начале работы программы. Если это данное не известно то можно либо сильно увеличить резервируемую память, либо рисковать ограниченность пространства для данных в массиве. Данную проблему решают связные списки.  Связанный список это структура данных, содержащая из взаимосвязанных блоков. Идея состоит в том, что бы создать класс, который поддерживал бы данные определённого типа, среди которых был бы указатель, связанный с другим объектом этого класса.

  28. Существуют три основных вида списков:

  • Однонаправленные списки  (очередь, стек);

  • Двунаправленные списки (дек и т.д.);

  • Деревья.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]