Array von Funktionen
-
chrische5 schrieb:
... und es wäre hilfreich, weil übersichtlich, wenn ich viele Funktionen so zusammenfassen könnte und dann nur noch einen Parameter ...
Das wäre überhaupt nicht übersichtlich!
Aha, Du will in der Tat Funktionen in ein Array schreiben und die Funktion über den Laufparameter des Arrays ansprechen. Ich glaube da nicht daran, dass das funktionieren wird/kann.
-
Nein. Das ist kein Problem. Ich habe eine Funktion an die ich eine Parameter übergeb. Mit diesem mache ich dann diverse Berechnungen und am Ende würde ich gerne eine Funktion in Abhängigkeit von diesem Parameter aufrufen. Ich konnte also eine switch-Anweisung machen und alle möglichen Zustände vom Parameter überprüfen, da es aber 13 sein können finde ich das nicht sehr attraktiv. Also dachte ich mir, dass ich ja eine Funktionsarray aufrufe könnte, in dem ich den Parameter im Namen angebe. Also genauso, wie ich ein normales array benutze. Ich wollte nur wissen, ob so was möglich ist und wenn wie.
chrische
-
Meinst du vielleicht sowas ?
typedef float (*myfunc)( int param1, int param2 ); float testfunc1( int param1, int param2 ) { return 1.0; } float testfunc2( int param1, int param2 ) { return 2.0; } float testfunc3( int param1, int param2 ) { return 3.0; } myfunc array_of_functions[3] = { testfunc1, testfunc2, testfunc3 }; int main(int argc, char* argv[]) { for ( int i=0; i<3; i++ ) { float result = array_of_functions[i]( 0,0 ); printf( "%f", result ); } return 0; }
-
Hallo
Das schaut sehr gut aus. Ich werde es mal probieren und mich bei eventuellen Probelem wieder melden. Vielen Dank für Eure schnelle Hilfe.
chrische
-
Hallo
chrische5 schrieb:
... und es wäre hilfreich, weil übersichtlich, wenn ich viele Funktionen so zusammenfassen könnte und dann nur noch einen Parameter ...
Das wäre überhaupt nicht übersichtlich!
Ob es übersichtlich ist oder nicht sollte doch nun wirklich derjenige entscheiden, der sein Programm kennt.
Ich habe es leider nicht richtig hinbekommen. Ich arbeite an einer Dialogfeldbasierten Anwendung und habe versucht in der *.cpp Datei meiner eigenen CCheckBedingung-Klasse alles zu zu schreiben, wie es vorgeschlagen wurde:
typedef int(*myFunctions) (CWuerfel arWuerfel[]);Das ganz oben und dann die Funktionen. Am Ende steht:
myFunctions aCheckFunctions[13]={CCheckBedingung::CheckEinsen,CCheckBedingung::CheckZweien,CCheckBedingung::CheckDreien,CCheckBedingung::CheckVieren,CCheckBedingung::CheckFuenfen,CCheckBedingung::CheckSechsen,CCheckBedingung::CheckDreierPasch,CCheckBedingung::CheckViererPasch,CCheckBedingung::CheckFullHouse,CCheckBedingung::CheckKleineStrasse,CCheckBedingung::CheckGrosseStrasse,CCheckBedingung::CheckChance,CCheckBedingung::CheckKniffel};Ist leider etwas lang geworden, aber es sind nun mal 13 Funktionen.
Nun bekomme ich folgende Fehlermeldungen(es sind genau 13):
d:\Visual Studio Projekte\Kniffel\CheckBedingung.cpp(293): error C2440: 'initializing' : cannot convert from 'int (__thiscall CCheckBedingung::* )(CWuerfel [])' to 'myFunctions'
Wo liegt mein Fehler? Muss ich noch in der *.h -Datei rumschreiben?
chrische
-
Klingt mir eher nach einem Fehler im Design *grumpf*

Poste doch mal die Funktionsrümpfe deiner einzelnen Check-Funktionen, dann wird sich schon eine Möglichkeit zeigen, das alles etwas eleganter zu lösen.
-
Hallo
Ich weiss leider nicht genau, was der Funktionsrumpf ist, baer ich poste mal das hier:
int CCheckBedingung::CheckEinsen(CWuerfel arWuerfel[]) { //int Variable für die Gesamtpunktzahl int iSummeEinsen=0; //Schleife für alle fünf Würfel for(int i=0;i<5;i++) //wenn Würfelzustand =1 oder Würfelzustand =7 (1, aber gesetzt) wird Summe um eins erhöht if((arWuerfel[i].m_iCheckZustand==1) || (arWuerfel[i].m_iCheckZustand==7)) iSummeEinsen+=1; //Summe wird zurückgegeben return iSummeEinsen; }Natürlich ist das nicht bei jeder Funktion genau dasselbe.
chrische
-
Und dein Ziel ist, die Punkte eines einzelnen Wurfes zu ermitteln oder verfolgst du noch weitere Ziele?
-
Hallo
Mein Ziel ist es, dass wenn jemand dreimal gewürfelt hat und sich dann entschieden hat, welches Feld er belgen möchte (eonsen, DreierPasch, Kniffel, Kleine Strasse,...) die dazugehörige Funktion aufgerufen wird. Ich würde also gerne einer Funktion einen int-Parameter übergeben, in dem steht, welches Feld geklickt wurde und dann die Funktion aufrufen. Da wäre es natürlich praktisch keine switch-Anweisung zu schreiben, sondern nur den Funktionsnamen und den Parameter anzugeben.
chrische
-
Dieser Thread wurde von Moderator/in Unix-Tom aus dem Forum MFC (Visual C++) in das Forum C++ verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Ist leider etwas lang geworden, aber es sind nun mal 13 Funktionen.
Nun bekomme ich folgende Fehlermeldungen(es sind genau 13):
d:\Visual Studio Projekte\Kniffel\CheckBedingung.cpp(293): error C2440: 'initializing' : cannot convert from 'int (__thiscall CCheckBedingung::* )(CWuerfel [])' to 'myFunctions'
Die Compilermeldung kommt daher, dass deine Methoden einen this-Pointer benötigen, der bei dieser Art des Funktionsaufrufes nicht zur Verfügung steht.
Wenn deine Methoden in der Klasse CCheckBedingung keinen Zugriff auf Variablen der Klasse benötigen, kannst du diese ja auch static deklarieren.
Dann funktionierts auch mit dem Funktionspointerarray.
typedef int (*FUNCTIONPOINTER)(CWuerfel*); class MyClass { public: MyClass(); static int testfunc1(CWuerfel*) { return 1; } static int testfunc2(CWuerfel*) { return 2; } static int testfunc3(CWuerfel*) { return 3; } }; FUNCTIONPOINTER funcpointerarray[3] = { MyClass::testfunc1, MyClass::testfunc2, MyClass::testfunc3 };
-
Hallo
Ich habe das jetzt mal probiert, obwohl ich ehrlich gesagt nicht genau weiss, was es bedeutet einen Funktion als static zu deklarieren (vielleicht kannst du mir da mal auf die Sprünge helfen) Mein code schaut jetzt folgendermaßen aus:
#pragma once #include "Wuerfel.h" typedef int(*myFunctions) (CWuerfel arWuerfel[]); class CCheckBedingung { public: CCheckBedingung(void); ~CCheckBedingung(void); // Checkt, ob 1en schon belegt wurden static void Sortieren(CWuerfel arWuerfel[]); //macht aus doppelten Augenzahlen eine Null static void DoppelteLoeschen(CWuerfel arWuerfel[]); // Checkt, wieviel Punkte man bekommt, wenn man auf Einsen klickt static int CheckEinsen(CWuerfel arWuerfel[]); // Checkt, wieviel Punkte man bekommt, wenn man auf Zweien klickt static int CheckZweien(CWuerfel arWuerfel[]); // Checkt, wieviel Punkte man bekommt, wenn man auf Dreien klickt static int CheckDreien(CWuerfel arWuerfel[]); // Checkt, wieviel Punkte man bekommt, wenn man auf Vieren klickt static int CheckVieren(CWuerfel arWuerfel[]); // Checkt, weiviel Punkte man bekommt, wenn man auf Fünfen klickt static int CheckFuenfen(CWuerfel arWuerfel[]); // Checkt, weiviel Punkte man bekommt, wenn man auf Sechsen klickt static int CheckSechsen(CWuerfel arWuerfel[]); //Checkt, wieviel Punkte man bekommt, wenn man auf DreierPasch klickt static int CheckDreierPasch(CWuerfel arWuerfel[]); //Checkt, wieviel Punkte man bekommt, wenn man auf ViererPasch klickt static int CheckViererPasch(CWuerfel arWuerfel[]); //Checkt wieviel Punkte man bekommt, wenn man auf Full House klickt static int CheckFullHouse(CWuerfel arWuerfel[]); //Checkt, wieviel Punkte man bekommt, wenn man auf Kleine Strasse klickt static int CheckKleineStrasse(CWuerfel arWuerfel[]); //Checkt, wieviel Punkt man bekommt, wenn man auf grosse Strasse klickt static int CheckGrosseStrasse(CWuerfel arWuerfel[]); //Checkt, wieviel Punkte man bekommt, wenn man auf Kniffel drückt static int CheckKniffel(CWuerfel arWuerfel[]); //Checkt, wieviel Punkte man bekommt, wenn man auf Chance klickt static int CheckChance(CWuerfel arWuerfel[]); bool m_abIsChecked[13]; }; myFunctions aCheckFunctions[13]={CCheckBedingung::CheckEinsen,CCheckBedingung::CheckZweien,CCheckBedingung::CheckDreien,CCheckBedingung::CheckVieren,CCheckBedingung::CheckFuenfen,CCheckBedingung::CheckSechsen,CCheckBedingung::CheckDreierPasch,CCheckBedingung::CheckViererPasch,CCheckBedingung::CheckFullHouse,CCheckBedingung::CheckKleineStrasse,CCheckBedingung::CheckGrosseStrasse,CCheckBedingung::CheckChance,CCheckBedingung::CheckKniffel};Leider bekomm ich jetzt eine neue Fehlermeldung aus der ich ebenfalls nicht schlau werde:
Kniffel error LNK2005: "int (__cdecl** aCheckFunctions)(class CWuerfel * const)" (?aCheckFunctions@@3PAP6AHQAVCWuerfel@@@ZA) already defined in CheckBedingung.obj
gefolgt von:
Kniffel fatal error LNK1169: one or more multiply defined symbols found
Vieleicht wisst ihr ja, was er will.
chrische
-
Kniffel error LNK2005: "int (__cdecl** aCheckFunctions)(class CWuerfel * const)" (?aCheckFunctions@@3PAP6AHQAVCWuerfel@@@ZA) already defined in CheckBedingung.obj
Liegt daran, dass du das Array in der Headerdatei definierst.
Jedesmal wenn du dann die Datei CheckBedingung.h in eine cpp includierst wird ein neues Array vom Compiler mit gleichem Namen angelegt. Das mag der Linker gar nicht, da er ja nicht weiss welches Objekt nun unter dem Namen angesprochen wird => Fehler ... already defined in ...
Lösung:
Pack die Zeile
myFunctions aCheckFunctions[13]={CCheckBedingung::Check...};in die cpp-Datei CheckBedingung.cpp.
Falls du aus anderen Files auch auf das Array zugreifen musst, deklariere das Array als extern im Headerfile CheckBedingung.h:
extern myFunctions aCheckFunctions[];Ich hoffe das hilft.
-
man kann für headerdateien auch die Übliche Vorgehensweise wählen und sie nur bedingt kompilieren, wenn sie noch nicht kompiliert worden sind:
#ifndef MYHEADER_H #define MYHEADER_H //dieser Teil wird vom Compiler nur einmal gelesen, //beim zweiten mal ist MYHEADER_H bereits definiert und //der Präprozessor entfernt den Code vorm kompilieren //natürlich sollte das definierte Symbol immer unterschiedlich sein #endifDamit werden mehrfache definitionen durch mehrfache Einbindung von Headern unmöglich.
-
@pumuckl: Includeguards helfen in diesem fall nicht.
Damit werden mehrfache definitionen durch mehrfache Einbindung von Headern unmöglich.
sollte eigentlich heissen :
Damit werden mehrfache definitionen durch mehrfache Einbindung von Headern in einer kompilationseinheit (sagt man das so ?) unmöglich.
Das problem hier ist aber das der gleiche Header in verschiedenen kompilationseinheiten eingebunden wird, daher befindet sich die variable dann in mehreren .obj-files und das mag der linker nicht.
Wie tvdog schon gesagt hat extern ist die lösung.
BTW Includeguards verhindern compilerfehler, extern verhindert linkerfehler.
Kurt
-
Hallo
Ich habe die typedef-Anweisung und die Array Deklaration in die *.h-Datei geschrieben und in der *.cpp-Datei steht der Rest:
*h-Datei:
typedef int(*myFunctions) (CWuerfel arWuerfel[]); myFunctions aCheckFunctions[13];*.cpp-Datei:
myFunctions aCheckFunctions[13]={CCheckBedingung::CheckEinsen,CCheckBedingung::CheckZweien,CCheckBedingung::CheckDreien,CCheckBedingung::CheckVieren,CCheckBedingung::CheckFuenfen,CCheckBedingung::CheckSechsen,CCheckBedingung::CheckDreierPasch,CCheckBedingung::CheckViererPasch,CCheckBedingung::CheckFullHouse,CCheckBedingung::CheckKleineStrasse,CCheckBedingung::CheckGrosseStrasse,CCheckBedingung::CheckChance,CCheckBedingung::CheckKniffel};In meiner Funktion rufe ich jetzt mit einen Feldparameter die gewünschte Funktion auf und bekomme dabei leider immer eine Fehlermeldung. Hier erstmal der Aufruf der Funktion:
int CKniffelDlg::DoClicked(int Feld) { //wenn Einsen bereits belegt sind, erscheint MessageBox mit Meldung if(m_cCheckBedingung.m_abIsChecked[Feld]) MessageBox("Sie haben dieses Feld bereits belegt"); //ansonsten werden die Punkte ausgegeben, Belegt-Varible auf true gesetzt und alle Würfel neu gewürfelt else { //Aufruf der Funktion CheckEinsen aus der Klasse CCheckBedingung, in der ermittelt wird, wie hoch die //Punktzahl beim Einserfeld ist und Zuweisung zur Variablen von IDC_STATICAUSGABEEINSEN m_aiAusgabe[Feld]=m_cCheckBedingung.aCheckFunctions[Feld](arWuerfel);Das ist nicht die ganze Funktion, aber der wichtige Aufruf steht in der letzten Zeile. Wenn ich nun auf einen Button klicke und die Funktion DoClicked aufgerufen wird, bekomme ich die Fehlermeldung:
Unhandled exception at 0xcccccccc in Kniffel.exe: 0xC0000005: Access violation reading location 0xcccccccc.
Vielleicht wisst Ihr ja Hilfe, da Ihr bis jetzt ja immer Bescheid wusstet.
chrische
-
Hallo
Weiss keiner, was hier los sein könnte?
chrische
-
Vielleicht ist Feld kein gültiger Index für aCheckFunctions.
BTW: Das mit den static-Funktionen solltest du wieder rückgängig machen und stattdessen einen Funktionspointer auf ein Klassenelement benutzen.
-
Hallo
"Feld" ist ein gültiger Index, da ich 0 übergebe und das Array 13 Plätze hat (von 0-12) Warum ist das mit static ungünstig? Ich habe wie gesagt noch gar nicht richtig verstanden, was static eigentlich bringt.
chrische
-
Eine statische Methode hat keinen this-Pointer, d.h. alle Instanzen der Klassen teilen sich die Methode.