сряда, 30 април 2008 г.

pointer-to-member-function C++

(който не разбира заглавието - става дума за указатели към член-функции в класове на C++ - който и това не разбира да го прескочи :))

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

Основният проблем е, че типът на една функция, която е в клас не е просто връщана-стойност (*) (аргуенти), защото тези функции получават един неявен указател this, който сочи към данните на обекта. Освен това този указател е от различен тип за всеки клас (т.е не може просто да кажем че това е member функция и да стане) - трябва като цитираме съответна функция да кажем и от кой клас е:
името-на-класа::името-на-функцията
.
Сега вече типа става:
връщана-стойност (име-на-клас::*име-на-функция) (аргументи) [const]

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


class cls {
int mem_fun (const char *) const;
static void static_mem_fun (double, char);
};


Ако искаме да подадем mem_fun на някоя фунция (за да може тя да вика точно тази функция за даден обект - обекта отделно трябва да го дадем разбира се) трябва да я приемем по следния начин:
void mem_fun_user (const cls &c, int (cls::*f) (const char *) const) {
/*по този начин я викаме - обърнете внимание на скобите и звездата*/
/*ако c беше указтел към клас тогава викаме със '->*' */
int p = (c.*f) ("haha");
}

сега остава да покажа как се предава :)

void foo () {
cls c;
/*не слагайте допълнителни скоби, или аперсанта другаде - НЕ РАБОТИ - точно както съм го дал така :)*/
mem_fun_user (c, &cls::mem_fun);
}


Можете да подавате и указатели към оператори - просто трябва да ги изпишете (style="font-family:courier new;">&rational::operator +) - държат се като обикновенни функции (но се викат по интересно ;)).

При статичните функции е по-лесно - защото при тях няма този скрит указател this който казва на кой клас е. Т.е техния тип е като на обикновенна функция, а за да ги подадете пишете име-на-клас::име-на-функция както при член функциите

Ето една страничка с (може би) малко по-подробна информация по въпроса:
http://www.parashift.com/c++-faq-lite/pointers-to-members.html

понеделник, 28 април 2008 г.

Сефтето на блога

Ето го и първия пост :) Дано не зарежа и това начинание, както много други.
Като ми дойде музата пак ;)