type casting problem in C++

12 отговора 440 прегледа
#1

type casting problem in C++

Zdraveite :) Imam malko problemche i se nadiavam da mi pomognete:

class Dock
{
public:
void func(){}
} obj;

main()
{
void (*p1)();
p1 = obj.func; //error :(( namerih reshenie po dolu no isnikna drug problem

void (Dock::*pFunc)();
pFunc = obj.func; //it's OK

void* pVoid;
pVoid = pFunc; //error
}
Problema mi e che triabva da napalnia conteiner s pVoid koito so4i kam obj.func()
Mnogo blagodarnosti predvaritelno

Отговор
в отговор на dbrs #2

Re: type casting problem in C++

Ne moje. Shtoto ako mojeshe, shteshe da se poluchi mnogo hubav gyrmej (otde da znae kompilatora, che tryabva da predava i this?). Vij, ako Dock::func() e static, moje i da stane.

Отговор
в отговор на dbrs #3

Re: type casting problem in C++

njakade mai vidiah che cast ot function pointer kym void pointer e compiler dependent. zavisi kolko si smel s tvoia compiler. sigurno ima drug nachin :P

moite $0.02 :) nali i az sym dyrven filosof

bivsh dijkstra
Отговор
в отговор на dbrs #4

Re: type casting problem in C++

mojesh da si napravish kontainer ot ukazateli kym fn, a ako si golqm gyzar, mojesh da go napravish da e template

typedef void (Dock::*tpFunc)();

vector< tpFunc> boza;

Отговор
в отговор на dbrs #5

Re: type casting problem in C++

Ако ползваш борландския TList напиши в Google "TTypedList" и виж първата връзка. Има удобен темплит.

Отговор
в отговор на grouchy #6

Re: type casting problem in C++

Eto kakwo pishe w help-a na BorlandC++
"In C++, you cannot cast a member function pointer to a normal function pointer.
The reason being that a class member function takes a hidden parameter, the this pointer, thus it behaves very differently than a normal function pointer."

Probwai slednoto:
typedef void (Dock::*Func)();

Mozhesh da napravish container s Func, a ne s void*
Func pFunc = &Dock::func; //

(obj.*pFunc)();

Отговор
в отговор на Krasi #7

Re: type casting problem in C++

И аз си помислих, че има допълнителен аргумент и пробвах с VC. Там sizeof() дава 4, така че не е така. В Borland имаше някакво понятие closure, което представляваше два поинтера. Явно е компилатор-зависимо и затова не се допуска такова присвояване. Иначе може да стане ( на VC ) с reinterpret_cast.

Отговор
в отговор на Colombino #8

Re: type casting problem in C++

Borlandskoto __closure e lichno tqhno si razshitenie, neshto kato Delegate na C#, samo che kym samo 1 metod.

A inache - pomisli si vse pak kvo sha stane kato imash ptr kym nevirtualna i kym virtualna funkciq i sha ti stane qsno che ne mojesh prosto taka da kastvash kym kakvoto si iskash...

Отговор
в отговор на Colombino #9

Re: Colombino

Hi
Tova li imash predvid? Tova e parvoto neshto koeto probvah i ne stana:(

void* pVoid;
pVoid = reinterpret_cast<void*>(pFunc);

Vsashtnost iskam da si napravia neshto kato MSG_MAP. Functions mi sa s razlichen broi parametri i vrashtat razlichen type (Poluchawam imeto na funkciata koiato triabwa da izpalna i parametrite i). T.e problema mi e barzoto namirane na func i =>action. Ako imate niakakva ideia kak da go napravia shte sam vi mnogo blagodaren:)) sredata e VC++
Oshte edin pat 10x

Отговор
в отговор на dbrs #10

Samo za maistori

Shte ti pokazha kak da go naprawish bez da ti iskam pari, no towa e wish pilotazh ;-)
Po syshtia nachin sa realizirani ResponseTables. w BorlandC++.
Zatai dyh i se naslazhdawai, a ako go razberesh, shte stane programist ot teb ;-)


//==============================================================================
//
// class GENERIC
// ~~~~~ ~~~~~~~
// Generic class for casting pointer to objects and pointer to member functions
// Class is not actually defined or implemented anywhere
//
class GENERIC;

//
// typedef AnyPMF
// ~~~~~~~ ~~~~~~~
// generic pointer to member function
//
typedef void (GENERIC::*AnyPMF)();

typedef int (*TAnyDispatcher)(GENERIC&, AnyPMF, int, int);

//
// passes nothing and always returns 0
//
int
v_Dispatch(GENERIC& generic,
void (GENERIC::*pmf)())
{
(generic.*pmf)();
return 0;
}

//
// passes bool and always returns 0
//
int
v_B_Dispatch(GENERIC& generic,
void (GENERIC::*pmf)(bool),
bool param)
{
(generic.*pmf)(param);
return 0;
}

//
// passes bool and always returns int
//
int
i_B_Dispatch(GENERIC& generic,
int (GENERIC::*pmf)(bool),
bool param)
{
return (generic.*pmf)(param);
}

//==============================================================================
template <class T> class ResponseTableEntry {
public:
typedef void (T::*PMF)();

T* pObject;
TAnyDispatcher Dispatcher;
PMF Pmf;
};

//==============================================================================
template <class T>
inline void (T::*v_Sig(void (T::*pmf)()))()
{
return pmf;
}

//==============================================================================
template <class T>
inline void (T::*v_B_Sig(void (T::*pmf)(bool)))(bool)
{
return pmf;
}

//==============================================================================
template <class T>
inline int (T::*i_B_Sig(int (T::*pmf)(bool)))(bool)
{
return pmf;
}


//==============================================================================
//
class A
{
public:
void f_v() {MessageBox(0, "Void", "class A", MB_OK);}
void f_v_B(bool fl) {MessageBox(0, "Void - Bool", "class A", MB_OK);}
int f_i_B(bool fl) {MessageBox(0, "Int - Bool", "class A", MB_OK); return fl;}
};

class B
{
public:
void f_v() {MessageBox(0, "Void", "class B", MB_OK);}
void f_v_B(bool fl) {MessageBox(0, "Void - Bool", "class B", MB_OK);}
int f_i_B(bool fl) {MessageBox(0, "Int - Bool", "class B", MB_OK); return fl;}
};

//==============================================================================
void main()
{
typedef ResponseTableEntry<GENERIC> GenericTableEntry;
typedef ResponseTableEntry<A> ATableEntry;
typedef ResponseTableEntry<B> BTableEntry;
typedef ATableEntry::PMF A_PMF;
typedef BTableEntry::PMF B_PMF;

//Instances
A a;
B b;

//Initializing arrays
ATableEntry entriesA[] =
{
{&a, (TAnyDispatcher)::v_Dispatch, (A_PMF)v_Sig(&A::f_v)},
{&a, (TAnyDispatcher)::v_B_Dispatch, (A_PMF)v_B_Sig(&A::f_v_B)},
{&a, (TAnyDispatcher)::i_B_Dispatch, (A_PMF)i_B_Sig(&A::f_i_B)},
};

BTableEntry entriesB[] =
{
{&b, (TAnyDispatcher)::v_Dispatch, (B_PMF)v_Sig(&B::f_v)},
{&b, (TAnyDispatcher)::v_B_Dispatch, (B_PMF)v_B_Sig(&B::f_v_B)},
{&b, (TAnyDispatcher)::i_B_Dispatch, (B_PMF)i_B_Sig(&B::f_i_B)},
};

//Generic implementation
GenericTableEntry* entriesGeneric[6];
for (int i = 0; i < 3; i++)
{
entriesGeneric = (GenericTableEntry*)&entriesA;
entriesGeneric[3 + i] = (GenericTableEntry*)&entriesB;
}

//Call of methods
for (int i = 0; i < 6; i++)
{
GenericTableEntry& entry = *entriesGeneric;

(*entry.Dispatcher)(*entry.pObject, (AnyPMF&)entry.Pmf, i, 0);
}
}

Отговор
в отговор на Krasi #11

Re: Samo za maistori

Mnogo si welik. A i samochuwstwieto ti si go biwa.

Отговор
в отговор на Krasi #12

Re: Samo za maistori

Mnogo mnogo 10x. Ako vav foruma uchastvat samo takiva hora cena niama da ima:)))))
Ne sam ot golemite maistori, no shte se opitam da shvana ideata:)

Отговор
в отговор на dbrs #13

Oshte malko

template classes sa neveroqtno moshtno sredstwo. S tqh mogat da se naprawqt chudesa, no ne biwa i da se prekalqwa.
Sega shte ti pokazha kak mozhe da se izwika proizwolna member function s proizwolni arguments and return value.

Sega ti ostawa sywsem malko za da mozhesh da si reshish zadachata.

#define ARG(A) (((ArgStruct*)vp)->A)

//== void args Invokator =============================================
template <class CALC, typename RT>
class MethodInvokator0
{
public:
struct ArgStruct
{
CALC* c;
RT (CALC::*m)(void);
};

static RT Go(void* vp)
{
return (ARG(c)->*ARG(m))();
}
};

//== 1 arg Invokator =================================================
template <class CALC, typename RT, typename TA1>
class MethodInvokator1
{
public:
struct ArgStruct
{
CALC* c;
RT (CALC::*m)(TA1);
TA1 a1;
};

static RT Go(void* vp)
{
return (ARG(c)->*ARG(m))(ARG(a1));
}
};

//....

//== n arg Invokator =================================================
/*template <class CALC, typename RT, typename TA1, ..., typename TAn>
class MethodInvokatorN
{
public:
struct ArgStruct
{
CALC* c;
RT (CALC::*m)(TA1, TA2);
TA1 a1;
...
TAn an;
};

static void Go(void* vp)
{
(ARG(c)->*ARG(m))(ARG(a1), ..., ARG(an));
}
};
*/

//==============================================================================
template <class CALC, typename RT>
RT Invoke(CALC* c, RT (CALC::*m)(void))
{
typedef MethodInvokator0<CALC, RT> Invokator;
Invokator::ArgStruct as = { c, m };
return Invokator::Go(&as);
}

template <class CALC, typename RT, typename TA1>
RT Invoke(CALC* c, RT (CALC::*m)(TA1), TA1 a1)
{
typedef MethodInvokator1<CALC, RT, TA1> Invokator;
Invokator::ArgStruct as = { c, m, a1 };
return Invokator::Go(&as);
}

//....

/*
template <class CALC, typename RT, typename TA1, ..., typename TAn>
int Invoke(CALC* c, RT (CALC::*m)(TA1, ..., TAn), TA1 a1, ..., TAn an)
{
typedef MethodInvokatorN<CALC, RT, TA1, ..., TAn> Invokator;
Invokator::ArgStruct as = { c, m, a1, ..., an };
Invokator::Go(as);
}
*/


//==============================================================================
class A
{
public:
int f_i_v() {return 1;}
double f_d_v() {return 1;}
int f_i_i(int i) {return i;}
};

void main()
{
A a;

Invoke(&a, &A::f_i_v);
Invoke(&a, &A::f_d_v);
Invoke(&a, &A::f_i_i, 5);

//....
}

Отговор