wskaźnik na metodę -> problem z wywołaniem

0

Cześć,
Mam klasę, gdzie jest kilka metod. Każdy obiekt może wywołać tylko 1 określoną. Do tej pory rozwiązałem ten problem w ten sposób, że stworzyłem sobie drugą funkcję do której podawałem którą funkcję wywołać a ona przy pomocy switcha wybierała odpowiednią i zwracała wynik.
Obecnie pomyślałem, że lepszym (bardziej optymalnym) rozwiązaniem będzie zadeklarowanie wskaźnika do metody - czyli raz przypiszemy w obiekcie wskaźnik do wybranej funkcji i bez switcha będzie wykonywać się wybrana funkcja.
Problem jednak polega na tym, że nie mogę poradzić sobie z wywołaniem tej funkcji...
Ogólnie to wygląda mniej więcej tak:

class klasa
	{
	public:
		double funkcja1(double&);
		double funkcja2(double&);
		void inna_f(&double);

		double (klasa::*wskaznik)(double&);
		void set_fun(int type);
	}

void klasa::set_fun(int type)
	{
	switch(type)
		{
	case 0:
		wskaznik = &klasa::funkcja1;
		break;
	case 1:
		wskaznik = &klasa::funkcja2;
		}
	}
void klasa::inna_f(&double x)
	{
	double zmienna = *wskaznik(x);	//niedziała! próbowałem również: *klasa::wskaznik, *this->*wskaznik i jeszcze pare innych opcji
	}

Czy może mi ktoś pomóc i powiedzieć jak wywołać tą metodę przy pomocy wskaźnika?
Będę bardzo wdzięczny!

0

Dobra, znalazłem rozwiązanie ;-)
Trzeba zrobić tak: (this->*wskaznik)(x);

Trochę przydługo więc zamieniłem na funkcje statyczne - kompilator nie zgłasza błędów więc zakładam, że jest ok ;-) tylko bez żadnych this-ów, & i wyłuskiwania...

Mam jednak pytanie: dlaczego w tym zapisie this jest bez gwiazdki? Wydawało mi się, że this wywołujemy zawsze tak: *this...
pozdrawiam

0

Powinno być (this->*wskaznik)(x). Nawias jest wymagany!
http://ideone.com/LPRdN0

Edit: Pisałem to tak długo, że już sam znalazłeś rozwiązanie. :-/

this to wskaźnik, więc żadna gwiazdka nie jest potrzebna, odwołujesz się przez niego. Jeżeli chciałbyś gwiazdkę, to powinno być (*this.*wskaznik)(x). Możesz zainteresować się std::mem_fn, wtedy nie wygląda to tak strasznie.

0

this to wskaźnik na obiekt na rzecz, którego wywoływana jest dana metoda. Operator * wyłuskuje obiekt ze wskaźnika, więc zapis *this, de facto zwraca sam obiekt na który pokazuje this. Zatem instrukcje: this->metoda() i (*this).metoda() są z grubsza równoważne.
Nie rozumiem dlaczego obiekt klasy miałby wywoływać tylko 1 metodę? Jaki jest sens takiej konstrukcji?

0

Dziękuję bardzo za wyjaśnienie. Coś mi się w głowie kopło - macie całkowitą rację... Nie wiem dlaczego uważałem, że powinno być "*this->", chyba ze zmęczenia już nie myślę...

Endrju napisał(a):

Możesz zainteresować się std::mem_fn, wtedy nie wygląda to tak strasznie.

Tak sobie czytam o tym tutaj: http://msdn.microsoft.com/pl-pl/library/bb982851.aspx i na pierwszy rzut oka wydaje się to trochę bez sensu... Po co tyle zabawy jeśli można odwołać się do tych funkcji normalnie przez obiekt?
Natomiast w moim przypadku funkcje static sprawdziły się idealnie - są zdecydowanie wygodniejsze w użyciu ;-).

satirev napisał(a):

Nie rozumiem dlaczego obiekt klasy miałby wywoływać tylko 1 metodę? Jaki jest sens takiej konstrukcji?

Zamiast pisać może podam przykładowy kod i sam oceń który jest bardziej optymalny i w niektórych sytuacjach wygodniejszy ;-)

#include <iostream>
#include <string>
using namespace std;
class dziecko
	{
	public:
	int typ;
	int (*wsk)();

	dziecko(int t) : typ(t){set_wsk(t);}

	static int happy()
		{
		cout  << "Jestem bardzo szczęśliwy(a) ;-) " << endl;
		return 1;
		}

	static int sad()
		{
		cout  << "Jestem bardzo smutny(a) ;-( " << endl;
		return 0;
		}

	void set_wsk(int type)
		{
		switch(type)
			{
		case 0:
			wsk = happy;
			break;
		case 1:
			wsk = sad;
			break;
			}
		}

	void samopoczucie1() //TO
		{
		switch(typ)
			{
			case 0:
				cout  << "Jestem bardzo szczęśliwy(a) ;-) " << endl;
				break;
			case 1:
				cout  << "Jestem bardzo smutny(a) ;-( " << endl;
				break;
			}
		}

	int samopoczucie2() //VS TO ;-)
		{
		return wsk();
		}
	};

A w main:

void main()
	{
	cout << "Co jest łatwiej (i optymalniej) wykonać: " << endl;

	dziecko Jas(0);
	dziecko Tomek(1);

	Jas.samopoczucie1();
	Jas.samopoczucie2();

	Tomek.samopoczucie1();
	Tomek.samopoczucie2();	
return 0;
}
0

W sumie to samopoczucie1 powinno tak wyglądać:

void samopoczucie1()
		{
		switch(typ)
			{
			case 0:
				happy();
				break;
			case 1:
				sad();
				break;
			}
		}

VS

int samopoczucie2()
		{
		return wsk();
		}
0

Nie lepiej wzorzec state?

0

Tzn?

0

Mniej więcej coś takiego:

#include <iostream>
using namespace std;

class State {

	public:
		virtual void behaviour() = 0;
		virtual ~State() { }

};

class HappyMood: public State {

	public:
		void behaviour() {
			cout  << "Jestem bardzo szczęśliwy(a) ;-) " << endl;
		}

};

class SadMood: public State {

	public:
		void behaviour() {
			cout  << "Jestem bardzo smutny(a) ;-( " << endl;
		}

};

class Child {

	private:
		State* myMood;

	public:
		Child( State* myMood ): myMood( myMood ) {}
		void mood() const {
			if( myMood ) {
				myMood->behaviour();
			}
		}
		void changeMood( State* myNewMood ) {
			delete myMood;
			myMood = myNewMood;
		}

};

int main() {

	Child jas( new HappyMood() );
	Child tomek( new SadMood() );
	
	cout << "Jas: "; jas.mood();
	cout << "Tomek: "; tomek.mood();
	
	jas.changeMood( new SadMood() );
	cout << "Jas: "; jas.mood();


	return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1