Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Pointer na member funkciju

[es] :: C/C++ programiranje :: Pointer na member funkciju

[ Pregleda: 3640 | Odgovora: 7 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

tosa
上海, 中国

Član broj: 1811
Poruke: 1342
*.203.EUnet.yu

ICQ: 14293955
Sajt: https://github.com/milost..


+48 Profil

icon Pointer na member funkciju06.04.2002. u 11:12 - pre 267 meseci
Dakle potrebna mi je pomoc oko jednog problema...
Zelim da imam klasu koja ima member variablu koja je pointer na
member metod iste klase.

npr:

class test
{
public:
void jedan();
void (test::*dva)(); // ili kako je vec potrebno ...
};

test t;

Medjutim poziv na t.dva() izaziva sledece error C2064: term does not evaluate to a function... naravno to se ne desava ako izbacim test:: iz deklaracije
pointera, ali tada nije moguce dodeliti pointeru ptr na test::jedan ...

Pitanja:
Kako se to izvodi ?
Kako treba napisati ovo da bi f-ja znala sa kojim parcetom memorije radi,
mada verujem da je to u sklopu prvog pitanja :) ?

tosa
 
Odgovor na temu

sspasic
Sasa Spasic

Član broj: 3261
Poruke: 175
212.124.183.*

Jabber: sspasic@elitesecurity.org
ICQ: 35454521


Profil

icon Re: Pointer na member funkciju07.04.2002. u 19:38 - pre 267 meseci
Citat:
tosa:

Medjutim poziv na t.dva() izaziva sledece error C2064: term does not evaluate to a function... naravno to se ne desava ako izbacim test:: iz deklaracije
pointera, ali tada nije moguce dodeliti pointeru ptr na test::jedan ...

Pitanja:
Kako se to izvodi ?
Kako treba napisati ovo da bi f-ja znala sa kojim parcetom memorije radi,
mada verujem da je to u sklopu prvog pitanja :) ?

tosa


U ovom slucaju:
Code:

(t.*(t.dva))();

Prvo t je objekat za koji treba zvati funkciju, a njen pokazivac je u t.dva (zato i drugo t).

Mozda ce biti jasniji sledeci primer:
Code:

test t;
void (test::*tri)();
tri = &test::jedan;
(t.*tri)();

 
Odgovor na temu

tosa
上海, 中国

Član broj: 1811
Poruke: 1342
*.47.EUnet.yu

ICQ: 14293955
Sajt: https://github.com/milost..


+48 Profil

icon Re: Pointer na member funkciju08.04.2002. u 21:14 - pre 267 meseci
ovo sam uspeo i sam da provalim, ali:

da li postoji sansa da se u C++ regularno prepravi virtual table, tako da se
metod poziva uredno, kao i svaki drugi ... ?

dakle, ne zelim da smaram end-user-a sa "ruznim" pozivima ...

da pojasnim: zelim da napravim COM objekat sa izmenljivim metodama
shodno konfiguraciji, ali da to ostane transparentno za korisnika ...
za sada mi je samo palo na pamet resenje u C-u... :(

tosa
 
Odgovor na temu

sspasic
Sasa Spasic

Član broj: 3261
Poruke: 175
212.124.183.*

Jabber: sspasic@elitesecurity.org
ICQ: 35454521


Profil

icon Re: Pointer na member funkciju08.04.2002. u 23:58 - pre 267 meseci
Citat:
tosa:
da li postoji sansa da se u C++ regularno prepravi virtual table, tako da se
metod poziva uredno, kao i svaki drugi ... ?


Uh, nema potrebe za tim.

Probaj ovako:
1. Ako se svaki metod konfigurise nezavisno, dodaj jednu funkciju clanicu
koja ce zvati (t.*(t.dva))(); pa korisnik moze da zove nju

Code:

class test
{
public:
    // ...
    void   Dva() { (this->*(this->dva))(); }
    // ...
};


2. Ako se svi metodi klase konfigurisu odjednom, u paketu,
i to u vreme izvrsavanja:
Code:

class test_impl_base {
public:
    virtual void dva () = 0;
};

class test
{
public:
    test (test_impl_base *impl)
        : impl_ (impl) {}
    void dva() { impl_->dva (); }
private:
    test_impl_base *impl_;
};

// Prva varijanta konfiguracije
class test_impl_a : public test_impl_base {
    void dva ();
};

//...

test_impl_a t_impl;
test t (&t_impl);
t.dva();


3. Ako se konfiguracija zna u vreme kompajliranja:
Code:

template <typename TestImplType>
class test
{
public:
    void  dva() { impl_.dva (); }
private:
    TestImplType impl_;
};

class test_impl_a  {
public:
    void dva ();
};

// ...

test<test_impl_a> t;
t.dva();

 
Odgovor na temu

tosa
上海, 中国

Član broj: 1811
Poruke: 1342
*.ppp-bg.sezampro.yu

ICQ: 14293955
Sajt: https://github.com/milost..


+48 Profil

icon Re: Pointer na member funkciju13.04.2002. u 09:42 - pre 267 meseci
Ima potrebe za tim :)
Ono sto ja ne zelim (inace ne bih trazio pomoc) je function call overhead...
Dakle ne zelim da kada pozovem f-ju, bude vise od tog jednog poziva ...
Napominjem: performanse su kriticne !

tosa
 
Odgovor na temu

sspasic
Sasa Spasic

Član broj: 3261
Poruke: 175
212.124.183.*

Jabber: sspasic@elitesecurity.org
ICQ: 35454521


Profil

icon Re: Pointer na member funkciju13.04.2002. u 18:42 - pre 267 meseci
Citat:
tosa:
Ono sto ja ne zelim (inace ne bih trazio pomoc) je function call overhead...
Dakle ne zelim da kada pozovem f-ju, bude vise od tog jednog poziva ...


Ako su ove dopunske funkcije koje poziv preusmere na pravu f-ju inline (kao sto jesu u primeru koji sam poslao) dodatni call overhead ne postoji.

 
Odgovor na temu

tosa
上海, 中国

Član broj: 1811
Poruke: 1342
*.ppp-bg.sezampro.yu

ICQ: 14293955
Sajt: https://github.com/milost..


+48 Profil

icon Re: Pointer na member funkciju14.04.2002. u 11:13 - pre 267 meseci
Overhead postoji zato sto to ne mogu da budu inline f-je !
Kao sto sam napisao, to mi treba za COM objekat a ne za internu upotrebu u
nekom programu ...


tosa
 
Odgovor na temu

sspasic
Sasa Spasic

Član broj: 3261
Poruke: 175
212.124.183.*

Jabber: sspasic@elitesecurity.org
ICQ: 35454521


Profil

icon Re: Pointer na member funkciju18.04.2002. u 16:50 - pre 267 meseci
Citat:
tosa:
Overhead postoji zato sto to ne mogu da budu inline f-je !
Kao sto sam napisao, to mi treba za COM objekat a ne za internu upotrebu u
nekom programu ...
tosa

U poslednjem CUJ (Online) postoji tekst o State Design Patternu
pomocu pokazivaca na funkcije clanice koje takodje ima
call overhead, ali me je nateralo da probam jos jednom
(cisto da se ostane u formi ;)

Evo resenja (prilicno lici na ono iz CUJ ali ima svojih prednosti):
Code:


#include <iostream>
#include <cassert>

template<typename ReturnTypeT, class ClassT, typename SignatureT>
struct FunctionTraits {
    typedef ReturnTypeT       ReturnType;
    typedef ClassT            ClassType;
    typedef SignatureT        Signature;
};

template <class StateType, class Cfg1Type, class Cfg2Type>
class Selector {
    StateType state;
public:
    Selector (StateType s) : state (s) {}

    void Change (StateType s) { state = s; }

    template <typename FuncTraits>
    typename FuncTraits::Signature Select (const FuncTraits &, typename FuncTraits::ClassType &c) const {
        FuncTraits method_switcher;
        typename FuncTraits::Signature mem_func = 0;
        
        switch (state) {
        case Cfg1Type::choose:
            mem_func = Cfg1Type::get_func(method_switcher);
            break;
        case Cfg2Type::choose:
            mem_func = Cfg2Type::get_func(method_switcher);
            break;
        default:
            assert (0);
        }
        return mem_func;
    }
};

class Cls {
public:

    struct Dispatcher {
        typedef FunctionTraits<void, Cls, void (Cls::*)()>    Func1;
        typedef FunctionTraits<bool, Cls, bool (Cls::*)(int)> Func2;
    };

private:

    typedef int StateType;


    struct CfgA {
        enum { choose = 1 };
        static Dispatcher::Func1::Signature get_func(Dispatcher::Func1 &) { return &Cls::f1a; }
        static Dispatcher::Func2::Signature get_func(Dispatcher::Func2 &) { return &Cls::f2a; }
    };

    struct CfgB {
        enum { choose = 2 };
        static Dispatcher::Func1::Signature get_func(Dispatcher::Func1 &) { return &Cls::f1b; }
        static Dispatcher::Func2::Signature get_func(Dispatcher::Func2 &) { return &Cls::f2b; }
    };

    void f1a () { std::cout << "f1a" << std::endl; }
    void f1b () { std::cout << "f1b" << std::endl; }
    bool f2a (int) { std::cout << "f2a" << std::endl; return true; }
    bool f2b (int) { std::cout << "f2b" << std::endl; return true; }

    friend struct Cls::CfgA;
    friend struct Cls::CfgB;

    Selector<StateType, CfgA, CfgB> selector;

public:
    enum { STATE_A = CfgA::choose, STATE_B = CfgB::choose };

    Cls () : selector (STATE_A) {}

    void Change (StateType state) { selector.Change (state); }

    void f1 ();
    bool f2 (int n);

};

void Cls::f1 () { (this->*(selector.Select(Dispatcher::Func1(), *this)))(); }
bool Cls::f2 (int n) { return (this->*(selector.Select(Dispatcher::Func2(), *this)))(n); }

int main ()
{
    Cls cl;
    cl.f1 ();
    cl.f2 (1);

    cl.Change (Cls::STATE_B);
    cl.f1 ();
    cl.f2 (1);

    cl.Change (Cls::STATE_A);
    cl.f1 ();
    cl.f2 (1);

    return 0;
}



Gde su prednosti:
1. Pozivi metoda klase nisu inline, pa moze da se koristi za COM objekte.
Naravno, ako ne postoji takvo ogranicenje, mogu biti i inline.
2. Sve sto se odigra u pozvanoj funkciji jeste inline.
3. Nema poziva virtuelnih funkcija.
4. Mozes da napravis vise grupa metoda i da ih posebno konfigurises -
trebaju ti samo CfgX klase i odgovarajuci selector objekat.

Ako ti treba varijanta sa vise konfiguracija od dve, promeni Selector.
I on bi mogao da se napravi u varijanti za 2, 3, 4... konfiguracije.

Neke stvari su malo ruzne (npr. izbor Select funkcije pomocu dummy parametra umesto pomocu
Select<Dispatcher::Func1>(*this), i Dispatcher je public zato sto VC++ tu pogresno
(bar mislim) prijavljuje greske. GCC se mnogo vise ponasa onako kako bi covek to ocekivao
od lepo vaspitanog kompajlera iz dobre kuce.

Ostaje problem sto se pri prekonfigurisanju promeni samo mapiranje metoda, a promenljive clanice
ostaju iste, ali mislim da bi i to moglo da se napravi. Npr. u Selector se doda jos jedan
template parametar (StateSpecificData) i pokazivac tog tipa koji bi bio apstraktna klasa za klase koje
cuvaju podatke specificne za neko stanje; Change bi alocirao ove podatke kod promene stanja,
a iz f1a, f1b, f2a, f2b bi moglo da se pristupa tim podacima
(dohvatis ih sa StateSpecificData *data = selector->get_internal_data ();).

Cudo jedno sta sve moze da se napravi ovim template<vratolomijama> ;)

Nego, ima tu jos nesto... Neka me ispravi neko ko vise koristi VC++, ali mislim da
poziv COM metoda vec unosi prilican overhead tako da jedan poziv funkcije vise ili manje
ne menja bitno stvari.

Pozdrav,
Spaske
 
Odgovor na temu

[es] :: C/C++ programiranje :: Pointer na member funkciju

[ Pregleda: 3640 | Odgovora: 7 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.