Avatar billede bowmo Nybegynder
03. juni 2008 - 15:34 Der er 3 kommentarer

Function pointers

Lad os antage jeg har x antal class'es, der alle indeholder en funktion som :

AnsiString __fastcall TDoFunc::Parse(AnsiString);

(anden classe indeholder så :
AnsiString __fastcall TDoBatch::Parse(AnsiString);)

De er ikke nedarvet efter en overordnet class (endnu.. kommer måske lidt senere)

Jeg vil så gerne have oprettet en liste af pointere til disse funktioner i en anden class, og har prøvet følgende :

typedef AList {
int index;
AnsiString (Parse*)(AnsiString);
} TAList;
typedef TAList * PAList;

TDoFunc *DoFunc;
TDoBatch *DoBatch;
{
DoFunc = new TDoFunc();
DoBatch = new TDoBatch();
PAList AStruct;
AStruct = new TAList;

AStrict->Parse = &DoFunc->Parse;
}

Ovenstående fejler med :
[C++ Error] Script1.cpp(332): E2034 Cannot convert 'AnsiString (_fastcall * (_closure )(AnsiString))(AnsiString)' to 'AnsiString (_fastcall *)(AnsiString)'

Jeg vil mene det burde være muligt at gøre.. men hvad er det lige der gør at jeg ikke kan få det til at virke?
Avatar billede bertelbrander Novice
04. juni 2008 - 22:34 #1
I C++ kan man ikke lave en generisk funktions pointer der peger på funktioner i vilkårlige klasser.

Den lette måde er at lade alle klasserne arve fra den samme klasse, hvori funktionen er erklæret (pure) virtual.

Du kan også lave et indirekte opslag gennem en pointer til objektet og en funktions pointer.

Problemet er at for at kalde en vilkårlig funktion i en vilkårlig klasse kræves to ting, en pointer til funktionen og en pointer til objektet, en funktionspointer peger kun på funktionen, så du skal selv fremskaffe objektet.
Avatar billede bowmo Nybegynder
04. juni 2008 - 23:22 #2
Jeg blev stædig, efter en kollega sagde at det ikke rigtigt kunne lade sig gøre, og brugte et par timer på at google efter et svar.. :)

Endte med at lave følgende trick :

typedef AnsiString __fastcall (__closure *pt2ParserType)(AnsiString);
typedef AList {
AnsiString Name;
pt2ParserType pt2Parser;
} TAList;

og i min kode :
{
DoFunc = new TDoFunc();
DoBatch = new TDoBatch();
TList *list;
list = new TList();
TAList *AStruct;
AStruct = new TAList;

AStruct->pt2Parse = &DoFunc->Parse;
list->Add(AStruct);
AStruct = new TAList;
AStruct->pt2Parse = &DoBatch->Parse;
list->Add(AStruct);

senere kan jeg så :
for (int i=0;i<list->Count;i++)
{
  AStruct = (TAList *)list->Items[i];
  AStruct->Parse("xx");
}

Ovenstående er afprøvet i BCB 6.0..

Det kan godt være det er en borland specifik måde at gøre tingene på, og at det ikke er særlig portabel til andre compilere, men det er ikke afgørende lige nu..
Avatar billede bertelbrander Novice
05. juni 2008 - 01:14 #3
__closure  er det trick der gør det muligt med BorlandC++, det trick virker ikke med andre kompilere.

Det har sandsynligvis været nødvendig for Borland at lave den konstruktion i C++, fordi deres GUI framework er lavet i Delphi, hvor man uden videre kan gøre det du ønsker.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester