Wskaźnik do funkcji składowej klasy

2013-12-10 14:16

Rejestracja: 6 lat temu

Ostatnio: 5 lat temu

Lokalizacja: 100lica

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)();

Z zawodu księgowy. Programować dopiero się uczę, więc proszę o wyrozumiałość ;). W kręgu zainteresowań: sztuczna inteligencja (SSN, AG, LR etc.).

Pozostało 580 znaków

2013-12-10 15:15

Rejestracja: 14 lat temu

Ostatnio: 2 dni temu

1

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


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Pozostało 580 znaków

2013-12-10 15:19

Rejestracja: 6 lat temu

Ostatnio: 5 lat temu

Lokalizacja: 100lica

0

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


Z zawodu księgowy. Programować dopiero się uczę, więc proszę o wyrozumiałość ;). W kręgu zainteresowań: sztuczna inteligencja (SSN, AG, LR etc.).

Pozostało 580 znaków

2013-12-10 15:24

Rejestracja: 14 lat temu

Ostatnio: 2 dni temu

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))();`


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Pozostało 580 znaków

2013-12-10 15:47

Rejestracja: 6 lat temu

Ostatnio: 5 lat temu

Lokalizacja: 100lica

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?


Z zawodu księgowy. Programować dopiero się uczę, więc proszę o wyrozumiałość ;). W kręgu zainteresowań: sztuczna inteligencja (SSN, AG, LR etc.).

Pozostało 580 znaków

2013-12-10 16:35

Rejestracja: 14 lat temu

Ostatnio: 2 dni temu

1

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

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

Możesz wykonać poza klasą.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Pozostało 580 znaków

2013-12-10 16:46

Rejestracja: 16 lat temu

Ostatnio: 7 godzin temu

(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.

edytowany 2x, ostatnio: Azarien, 2013-12-10 16:52
Jedyne zastosowanie jakie widziałem to mapowanie handlerów wiadomości, chociaż to da się inaczej napisać. - kq 2013-12-10 17:08
@kq: próbowałem jakiś czas temu zaimplementować na tym eventy takie jak w Delphi albo C#, i okazało się tak upierdliwe, że przestałem się dziwić dlaczego żadna z powszechnie znanych bibliotek w C++ tego tak nie robi. - Azarien 2013-12-10 17:49

Pozostało 580 znaków

2013-12-10 20:18

Rejestracja: 6 lat temu

Ostatnio: 5 lat temu

Lokalizacja: 100lica

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ł...


Z zawodu księgowy. Programować dopiero się uczę, więc proszę o wyrozumiałość ;). W kręgu zainteresowań: sztuczna inteligencja (SSN, AG, LR etc.).
Co za problem napisać sobie odpowiednią klasę szablową? - _13th_Dragon 2013-12-10 21:20

Pozostało 580 znaków

2013-12-10 21:15

Rejestracja: 6 lat temu

Ostatnio: 5 lat temu

Lokalizacja: 100lica

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))();

Z zawodu księgowy. Programować dopiero się uczę, więc proszę o wyrozumiałość ;). W kręgu zainteresowań: sztuczna inteligencja (SSN, AG, LR etc.).

Pozostało 580 znaków

2013-12-10 21:21

Rejestracja: 14 lat temu

Ostatnio: 2 dni temu

0

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


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Pozostało 580 znaków

kq
2013-12-10 21:31
kq
Moderator C/C++

Rejestracja: 6 lat temu

Ostatnio: 6 godzin temu

Lokalizacja: Szczecin

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


edytowany 1x, ostatnio: kq, 2013-12-10 21:32

Pozostało 580 znaków

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