Wskaźnik do funkcji składowej klasy

0

Witam,
uprzejmie proszę o informację, dlaczego kompilator wywala błąd we wskazanym w komentarzu miejscu w poniższym kodzie:

#include "stdafx.h"
using namespace std;

#include <iostream>

class klasa
    {
    public:
        void (klasa::*wsk)();

        void metoda1()
            {
            cout << "funkcja 1" << endl;
            }

        void metoda2()
            {
            cout << "funkcja 2" << endl;
            }

        void set_method(int i)
            {
            if(i == 1)
                wsk = &klasa::metoda1;
            if(i == 2)
                wsk = &klasa::metoda2;
            }

        void fun2()
            {
            (this->*wsk)();
            }
    };

int _tmain(int argc, _TCHAR* argv[])
    {
    klasa B;
    B.set_method(2);
    (B.*wsk)();        //czemu tu jest błąd?!?
    B.fun2();

    getchar();
    return 0;
    }

Chodzi oczywiście o ten fragment:

(B.*wsk)();
1

Bo musi być tak:
(B.*(B.wsk))();

0

Jałć... co to za dziwny twór?!? ;-( -> przynajmniej działa... O_o
dziękuję!

2

Wskaźnik na metodę nie zapisuje obiektu.
B.wsk - to twój wskaźnik na metode:
(B.*ptr)() - wywołanie metody.
Teoretycznie możesz to wywołać tak: (B.*(A.wsk))(); lub tak: (A.*(B.wsk))();

0

Czyli innymi słowy, każdy obiekt może wywołać sam z siebie przypisany przez inny obiekt wskaźnik? Czyli tak, jakby każdy obiekt miał dostęp do innych obiektów O_o... Czy to nie dziwne?

1

Źle zrozumiałeś, następujący kod:

void (klasa::*wsk)();
wsk=&klasa::metoda1;

Możesz wykonać poza klasą.

2
(B.*(B.wsk))();

Na rzecz obiektu B (o tym mówi pierwsze B.) wywołujemy wskaźnik będący polem obiektu B (o tym mówi drugie B.).

Sam wskaźnik na funkcję nie przechowuje informacji, do jakiego obiektu należy (moim zdaniem do niedoróba, ale tak jest). Dlatego trzeba mu podać obiekt, na którym ma się funkcja wykonać. Może być to dowolny obiekt tej samej klasy.

Z drugiej strony, tenże wskaźnik jest tutaj polem tej samej klasy, więc trzeba mieć obiekt klasy by pobrać ten wskaźnik (niekoniecznie ten sam obiekt na rzecz którego funkcja jest wywoływana!). Nie musi tak być, wskaźnik wsk mógłby być zmienną globalną, lokalną, polem zupełnie innej klasy.

A tak na marginesie, ze względu na ułomność wskaźników do funkcji składowych w C++ — upierdliwą składnię i brak przywiązania do obiektu — nie widzę sensu ich używania, bo każde użycie wiąże się z próbą omijania tych dwóch wad.

0

Dziękuję bardzo za wyjaśnienia! A czy możecie mi jeszcze powiedzieć, czy jest jakaś szansa, żeby standard C++ został skorygowany w tym zakresie? Tzn. żeby można było przypisywać do wskaźnika funkcje bez konieczności korzystania z operatora zakresu i korzystania z nich bez używania gwiazdki wywołując funkcję (wskaźnik do funkcji) - tak jak robi się to w funkcjach...
Ogólnie to język C++ bardzo przypadł mi do gustu, ale niestety to jest jedna z dosłownie kilku rzeczy, którą bym jak najszybciej zmienił...

0

Mam jeszcze jedno pytanie (poza tym powyżej): czy jeśli wskaźnik na funkcję nie przechowuje informacji, do jakiego obiektu należy to czy wywoływanie takiej funkcji jest mniej wydajne, niż gdyby wskaźnik miał informacje o obiekcie? (oczywiście nie znacząco, ale czy jednak?).
Bo gdyby miał taką informację to wywołanie wyglądałoby tak:

obiekt.wskaznik_do_funkcji();

a teraz jest tak:

(obiekt.*(obiekt.wskaznik_do_funkcji))();
0

Nie możesz tej funkcji wywołać bez obiektu.

2
BeBetter napisał(a):

Dziękuję bardzo za wyjaśnienia! A czy możecie mi jeszcze powiedzieć, czy jest jakaś szansa, żeby standard C++ został skorygowany w tym zakresie? Tzn. żeby można było przypisywać do wskaźnika funkcje bez konieczności korzystania z operatora zakresu i korzystania z nich bez używania gwiazdki wywołując funkcję (wskaźnik do funkcji) - tak jak robi się to w funkcjach...
Ogólnie to język C++ bardzo przypadł mi do gustu, ale niestety to jest jedna z dosłownie kilku rzeczy, którą bym jak najszybciej zmienił...

To raczej wątpliwe, bo masz w standardzie funktory (#include <functional>: std::function,std::bind) oraz lambdy. Oba te rozwiązania potrafią pamiętać stan (czyli w Twoim przypadku this)
Przykład: http://ideone.com/mezDlk

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