Nu ved jeg jo ikke lige hvad du skal bruge det til - men man kan jo altid kalde member-funktioner indenfor samme klasse, dvs. M1 kalde M2 og omvendt. Hvis man skal kalde "mellem" to classes, bliver man nødt til at gemme adresserne i en global variabel ... MEN !!!
Hvis det er mellem to klasser, hvorfor laver du så ikke en global funktion - (eller en generelt klasse, som de to nye klasser arver fra) - det er vel den korrekte måde.
===========================
Og så ser jeg lige at bjarke er kommet mig i forkøbet ... Det er helt i tråd med hvad jeg sidder og prøver, men jeg kan heller ikke få min kompiler til at "æde" det:
#include <iostream.h>
class SomeClass { public: SomeClass(void); void M1(int); void M2(int); protected: int data; }; void (SomeClass::* ptrM1)(int); void (SomeClass::* ptrM2)(int);
SomeClass::SomeClass(void) { data = 0; ptrM1 = &SomeClass::M1; ptrM2 = &SomeClass::M2; } void SomeClass::M1(int add) { data = 0; // ptrM2(add); Giver compiler fejl this->M2(add); // Funker cout << "Data er nu: " << data << endl; } void SomeClass::M2(int add) { data += add; }
int main(void) { SomeClass a; a.M1(5); return 0; }
Det jeg mener er, at såfremt to klasser har behov for eksakt den samme funktionalitet, er det vel et tegn på at du ikke har fået opsplittet de to klasser godt nok. Eftersom de har dele af deres funktionalitet som er ens, bør du flytte den funktionalitet til en ny klasse KUN indeholdende det - og så lade de to "oprindelige" klasser arve fra den:
#include <iostream.h> #include <string.h>
class shared { public: shared(int x) { data = x; }; shared(void) { data = 0; }; void Mx(int add) { data += add; }; protected: int data; }; class inheritA : shared { public: inheritA(int x) : shared(x) { strcpy(name, "[Unknown]"); }; inheritA(char *n, int x) : shared(x) { strcpy(name, n); }; int M2(int add) { Mx(add); return data; }; int M1(int add) { data = 0; return M2(add); }; protected: char name[20]; }; class inheritB : shared { public: inheritB(int x) : shared(x) { /* No extra */; }; int M4(int add) { Mx(add); return data; }; int M3(int add) { data = 0; return M4(add); }; };
int main (void) { cout << "Så kører vi igen ..." << endl;
void (Someclass::* ptrM1)(int) angiver at vi har en variabel der hedder 'ptrM1' som indeholder en adresse til en 'void' member funktion i 'SomeClass' som tager en 'int' som parameter. Ideen er at ptrM1 skal kunne bruges på samme måde som man ville bruge M1. Denne void* kan du fint gemme i et array. (Men jeg forstår stadig ikke hvorfor den funktion du vil gemme adressen til, ikke er enten global, eller tilhører en "lavere" klasse.
F.eks. sådan her:
void (*ptrFunc)(int); void Func(int x) { cout << x << endl; } int main(void) { ptrFunc = Func;
Func(4); ptrFunc(3);
return 0; }
'Func(4)' og 'ptrFunc(3)' er begge et kald til 'Func'
Jeg har selv rodet lidt med det her på et tidspunkt, men tidligere har jeg givet op, fordi jeg simpelten ikke kan få det til at virke. Jeg har prøvet at kigge lidt på jeres forskellige eksempler, og må jo så konstatere, at jeg stadig ikke kan få det til at virke.
Problemet er, at funktioner på klasser ikke bare kan kaldes som almindelige funktioner. Hver klasse har jo sit private dataområde, som man kan tilgå fra alle funktionerne på klasserne. Det giver nogle problemer, hvis man bare kalder en pointer til funktionen. Jeg har ikke styr på alle detaljerne, men hvad jeg kan tænke mig frem til er følgende:
Når man definerer en klasse, og har flere objekter af den enkelte klasse, så vil man have et dataområde til lokale variabler for klassen for hver instans af klassen man opretter. Men man vil kun have selve funktionaliteten til klassen (funktioner, operatorer og constructor/destructor) liggende fysisk ét sted i hukommelsen. Når et objekt tilgår en member-function vil den derfor bruge den fælles fysiske funktionskode for dette. Det betyder, at når man kalder en memberfunction, så skal man ikke blot give parametrene med til funktionskoden, men også for hvilket fysisk objekt man kalder funktionen på. Det bliver normalt gjort bag om ryggen på udvikleren. Compileren smider selv referencen til objektet på stakken når den kalder funktionen på klassen. Det skal man altså finde en måde at gøre på, hvis man selv vil kunne lave sine member-funktions pointere.
Jeg har prøvet følgende, for at få den til at acceptere min funktionspointer (jeg har bygget videre på Soepro's eksempel):
tricket her er at typecaste til en almindelig funktion, som man så kan kalde. Problemet er blot: Det virker ikke!
Den kalder funktionen rigtigt, men objektet man kalder den på (this) er null. Og det er jo ikke så smart, når man så tilgår data variablen.
Der findes nok en løsning et eller andet sted, men jeg kender den ikke. Jeg har oven i købet prøvet at indsætte dette før funktionen, men det hjælper nul:
asm { push this }
I et desparat forsøg håbede jeg, at pointeren til objektet måske bare skulle ligge som det nederste objekt på stakken, når man kaldte funktionen. Men det skulle den ikke... this for funktionen er stadig NULL.
Jeg venter spændt på om der er nogle af jer andre der finder løsningen. Jeg håber dette har hjulpet en smule på forståelsen? Det er nok lidt rodet, men jeg har bare kastet mine tanker ned over tastaturet, det kunne være der var noget der gav en af jer en ide.
Jeg har fået det til at virke, men jeg ved ikke rigtig hvor god løsningen er. Efter jeg havde skrevet sidste indlæg kunne jeg ikke lade være; jeg skulle lige prøve en sidste desparat løsning. Men den lader til at virke, så her kommer den:
typedef void (* vfPtr)();
__asm { push add push this } (* (vfPtr*)(&ptrM2)) ();
Jeg havde en mistanke om at det ikke virkede før, fordi pointeren til objektet muligvis skulle ligge øverst på stakken, og parameterne derefter neden under. Så det jeg gør et, at jeg manuelt pusher parameterlisten på stakken (i dette tilfælde kun Add), og derefter pointeren til objektet som funktionen skal kaldes på. Og det virker faktisk...
Jeg ved dog ikke hvor brugbart det er. Det kræver jo i hvert fald at man også gemmer pointeren til objektet, sammen med pointeren til funktionen. Hvorfor overhovedet gå igennem alt det besvær? Kan det ikke laves med noget simpel nedarvning, som Soepro også anbefaler?
jeg skal kunne vælge fokus på forskellige objekter (af forskellige klasser) fra een klasse. Der er tale om nogle grafiske objekter, som skal opdaters, rent grafisk, ved fokus. Idet de forskellige objekter har forskellige fokus funktioner (de ser jo ikke ens ud) kan jeg vel ikke lave en "mother-of-all" klasse, som indeholder en fokus funktion og nedarve de forskellige klasser af denne !??
Hvis ikke dine forskellige funktioner ser ens ud, så kan du vel heller ikke lave en generel funktions pointer til de forskellige funktioner? Så virker funktions pointer løsningen jo heller ikke!
Hvordan ser de enkelte funktioner ud, og hvor meget magt har du over klasserne? er det fx. VCL eller MFC vi taler om?
Lad os få din kodestump ud - det du beskriver der, synes jeg at have set et eksempel på vha. template classes og en masse andet "fnidder".
Du KAN faktisk lave "mother-of-all" focus funktioner vha. 'virtual' keywordet - det eksempel er OGSÅ beskrevet i C++ Builder manualen. Fidusen er at have en generel Focus funktion som laver den nødvendige flyt af pointere etc. for så efterfølgende at kalde OBJECTET's draw funktion - og den er så specifik for de enkelte typer. Ved at bruge virtual sørger compileren selv for dette. (Det er også grunden til at alle objecter i f.eks. C++ Builder grundlæggende er TComponent baserede: man kan så altid kalde de generelle funktioner med objectet - når blot funktionen forventer en pointer til TComponent. Man kan ALTID kaste fra en given klasse til ALLE de klasser den er baseret på - og rent faktisk også fra en given basis-klasse til alle dens nedarvende klasser - vha. dynamic_cast<variabel type>(Variabel).
Men igen - det afhænger præcis af hvad det er du forsøger at gøre. (En anden løsning kunne jo være at gemme pointeren til klassen - og så bruge den sammen med en overloaded "standard" funktion. (Som så er defineret for hver eneste klasse der skal fungere.)
i min uvidenhed og manglende erfaring havde jeg glemt alt om muligheden for at lave member functions virtual...
tak for at oplyse mig...
Synes godt om
Ny brugerNybegynder
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.