ПредишенСледващото

Функционални показалки предоставят някои изключително интересни, ефективни и елегантни техники за програмиране. Можете да ги използвате, за да замени ключ / ако операторите, за да осъзнаят собствените си късно свързване (късния задължителни) или обратни повиквания (обратни повиквания). За съжаление, най-вероятно заради тяхната сложна синтаксис, в повечето компютърни книги и документи те включват много недружелюбно. Ако това не се казва за тях, нещо съвсем кратко и повърхностно. Те са по-малко грешки от нормалните указатели, никога няма да се разпределят или свободна памет за тях. Всичко, което трябва да се направи - е да се разбере какви са те и да се учат на синтаксиса. Но имайте предвид, че трябва винаги да се запитате дали наистина имате нужда от указател към функция. Приятно е да осъзнаем собствената си късно задължителен, но използването на съществуващите структури C ++ може да направи своя код за по-разбираеми и ясно. Един от аспектите в случай на късно свързване - време за изпълнение: ако се обадите на виртуална функция, вашата програма трябва да определи коя функция да се обадите. Това се прави чрез виртуалната таблица (Таблица V-), съдържащ всички възможни функции. На всяко обаждане отнема известно време и може би можете да спестите време, като използвате функцията указатели вместо виртуални функции. Може би не.

Когато искате да се обадите функция дребна монета () в определен момент, определен в етикета на програмата, просто сложи функцията обаждане дребна монета () в кю точката в изходния код. Тогава ще се съберат на кода, и всеки път, когато програмата въпрос за етикети, вашата функция се нарича. Всичко е наред. Но какво, ако не знаете в кой момент трябва да се извика функцията? Какво правите, когато искате да го реши по време на работа? Може би искате да използвате т.нар обратно повикване (функция за обратно извикване), или да изберете опция от група от възможни функции. Въпреки това, можете също така да реши проблема с помощта на изявление ключ. където ги извикате точно така, както желаете, с помощта на различни единици (клонове). Но има и друг начин: Използвайте функцията показалеца!

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

Имайки предвид, синтаксис, могат да бъдат идентифицирани два вида функционални указатели: един от тях - са указатели към обикновените функции C или статични член функции на C ++. Друг тип - са указатели към функции на потребителя не-статични в C ++. Основната разлика е, че всички указатели към член-функции не са статични трябва скрита аргумент: този указател към клас например. Винаги помнете: Тези два типа индекси не са съвместими един с друг.

Тъй като функция указател към нищо повече от една променлива. тя трябва да се определя като нормално. В следващия пример, определяме три указатели към функции: pt2Function, pt2Member и pt2ConstMember. Те посочват функциите, които вземат поне един аргумент от тип плувка и две Чар тип аргумент и връща вътр. В примерите, в C ++ се приема, че функция, при което ни знаци (не-статичен) член TMyClass.

В C, да се обадите на функцията, използвайки изрично dereferenced от * оператор към указател функция. Като алтернатива можете да използвате показалеца вместо името на функцията. В C ++, два оператора. * И -> *, съответно, се използват във връзка с инстанция на класа, за да се обадите на някой от неговата (не-статичен) член функция. Ако повикването е направено в рамките на друг член функция, можете да използвате показалеца на това.

Можете да подадете указател към функция като входен параметър на функцията. Например, имате нужда от него, ако искате да мине указател към функцията за обратно извикване. Следният код показва как да се мине указател към функция, която връща вътр. и отнема плава и две char'a:

3.1 Въведение в концепцията за обратни извиквания

Функционални указатели концепция дават обратни повиквания. Ако не сте сигурни как да използвате указатели към функции, върнете се към "Въведение към указател към функция." Аз ще се опитам да се въведе понятието за функция за обратно извикване с помощта на добре познатия вид функция, qsort. Тази функция сортира елементите на областта в съответствие с потребителски подобно. Област може да съдържа елементи от всякакъв вид; тя се предава на функцията за сортиране по ukzatel в празнотата. Също така да се предава размера на елемента и общия брой на елементите в областта. Сега въпросът е: как може функцията за сортиране за сортиране на елементите без никаква информация за техния вид? Отговорът е прост: функцията получава указател към функция сравнение, че отнема невалидни тройки в областта на два елемента, като се сравняват елементи и връща резултата, кодирана с вътр. По този начин всеки път, когато алгоритъмът вид изисква резултат от сравняването на два елемента, то е само функцията сравнение през показалеца функция: обади!

3.2 Как да се обадим на С?

3.3 qsort на пробата се използва код

Следната primetre сортирани масив от тип поплавък.

3.4 Как да се обадим в член функции Statcheskoy?

По същия начин, както това се прави в функция С. Функцията статичен член не се нуждае от един обект, който ще предизвика, и по този начин има подпис подобен на подпис С-функции с едно и също призвание конвенция, поиска аргументи и да се върнете тип.

3.5 Как да се обадим в член функции Nestatcheskoy? Подходящи опаковки (подход на обвивка)

Указатели към член-функции не са статични са различни от прост ukzateley с функции в C, тъй като те трябва да издържите клас обект чрез указател към анулира. По този начин, проста функция указатели и член-функции не са статични имат различни и несъвместими подписи! Ако искате да се позова на член на даден клас, трябва само да се замени в кода си прост указател към указател функция на член функция. Но това, което можете да направите, ако искате да се обадите nestatichsky член на който и да е клас? Тя е малко по-трудно. Трябва да се напише функция статично член като обвивка. Статично член функция е същата сигнатура като функция в C! След това можете да показалеца на обекта, че функцията член искате да се обадите, за да анулира * и го предаде на опаковката, като допълнителен параметър или чрез глобална променлива. Ако използвате една глобална променлива, че е много важно да се уверите, че тя винаги ще сочи към правилния обект! Разбира се, можете да подадете параметри да извикаме функцията член. Обвивка води до недействителност указател към указател към обект от клас sootvetstvuyuego и призовава функцията член. По-долу са дадени два примера.

Пример А: индекс, инстанция в класа се предава като допълнителен параметър

функция DoItA прави нещо с обекти от клас TClassA, която съдържа обаждане. Така TClassA указател към обект клас и указател към статична функция обвивка TClassA :: Wrapper_To_Call_Display прехвърля в DoItA. Тази обвивка е функцията за обаждане. Можете да напишете произволни други класове са същите като TClassA и да ги използвате с DoItA, толкова дълго, тъй като те осигуряват необходимите функции. Забележка: Това решение може да бъде полезно, ако сте проектиране свой собствен интерфейс за обратно повикване. Тя е много по-добре от второто решение, което използва глобална променлива.

Пример Б: Index, инстанция в класа се съхраняват в глобалната променлива,

функция DoItB прави нещо с обекти от клас TClassA, която съдържа обаждане. Указател към функция обвивка статичното TClassA :: Wrapper_To_Call_Display предава DoItA. Тази обвивка е функцията за обаждане. Обвивката използва глобалната променлива празнотата * pt2Object и извършва прецизна я шофиране към указател към инстанция TClassB. Това е много важно, че винаги ще се инициализира глобална променлива да сочи към правилния инстанция на класа. Можете да напишете произволни други класове са същите като TClassB и да ги използвате с DoItA, толкова дълго, тъй като те осигуряват необходимите функции. Забележка: Това решение може да бъде полезно, ако сте с помощта на интерфейс за обратно повикване, която не може да се променя. Това не е добро решение, защото chtoispolzovanie глобална променлива е много опасно и може да доведе до сериозни грешки.

4.1 Какви са Functors?

Functors него - функция с държавата. В C ++ можете да ги приложи като клас с един или повече частни членове да съхранявате състояние и с претоварен оператор () да изпълнява тази функция. Functors да оформят функционални указатели C и C ++. Използването на концепцията за шаблони и полиморфизъм. Можете да създадете списък от указатели към функции членки на произволни класове и ги наричат ​​всички през същия интерфейс, без да се налага да се притеснявате за техния клас или нужда от указател към инстанция на класа. Само за тази цел всички функции трябва да имат един и същ тип и връщане на параметрите на повикването. Понякога functors са известни като затваряне. Можете да използвате и functors да приложат обратни повиквания.

4.2 Как да се прилагат functors?

Първо, имате нужда от клас TFunctor база, която осигурява виртуална функция наречена Call или виртуална претоварен оператор (), с който можете да се обадите член функция. Какво предпочитате, претоварената оператора, или функцията като Call, - зависи от вас. От базов клас, можете да наследи клас шаблон TSpecificFunctor, който се инициализира конструктор, който се указател към обекта и указател към член функция. Извлечения клас отменя функцията Call и / или оператор () на базовия клас: неопределена във версията, на което се обаждате член функция с използване на запаметените указатели към обекта и член функция. Ако не сте сигурни как ispozovat указатели към функции, се отнасят до моето Въведение в функционални указатели.

4.3 Пример за functor

В следващия пример имаме две класни стаи, те осигуряват функция по-долу "Дисплей", който не връща нищо (свободен), и изисква низ (Конст Чар *) като входен параметър. Ние създаваме масив от две насоки TFunctor и го инициализира с две указатели към TSpecificFunctor, които капсулират указатели към обекти и указатели към членове и TClassA TClassB съответно. След това ние използваме масив от functors да се обадя на съответните функции членки. За да се изпълни функцията обаждане, указател към обекта не се изисква и не е нужно да се притеснявате повече за класовете!

5.1 Въведение в указатели към функции

5.2 Функция за обратно извикване и функции

Раздел 3.5. Пример А

В този пример, показалецът на превръщането обърква TClassA клас обект да анулира * DoItA във функцията на предаване, и след това обратна трансформация на показалеца на TClassA обвивка функция TClassA :: Wrapper_To_Call_Display (същото се отнася за пример В). Подобни проекти са подходящи (тъй като другите нямат избор), ако искате да работите с функции като pthread_create () (libpthread.so), който приема като входни параметри невалидни *. Във всеки случай, този пример ще работи само правилно, ако DoItA наистина премина указател към TClassA. Но какво се случва, ако по погрешка вместо указател към TClassA ще бъдат прехвърлени към нещо друго? Компилаторът не признава грешката, нищо няма да се предотврати преустроена за уриниране * указател към INT, например. За по-голяма яснота, аз малко се промени например (exampleA.cpp):
  • TClassA в клас добавя два елемента тип INT - а като X,
  • функционира TClassA :: дисплей показва стойността на х,
  • в Callback_Using_Argument () функция създава две променливи, първо - клас обект TClassA, от друга - INT тип; Освен това, както се нарича DoItA функция.
Не е трудно да се отгатне, че функция DoItA, получавайки като вход указател към INT, е направено, за да го меко казано, не е, както се очаква. Вместо стойността TClassA :: х изглежда несигурно набор от битове, за да го кажем по-просто - боклук. Възможно решение на този проблем - правя Wrapper_To_Call_Display DoItB и шаблонни функции (exampleB.cpp). Тъй като междинно съединение не подходящ специализация, компилаторът генерира съобщение за грешка.

Сайт с uCoz

Подкрепете проекта - споделете линка, благодаря!