Array von Funktionen
-
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.
-
Hallo
In Ordnung und warum ist das in meinem Fall schlecht. Hilft mir das bei der Fehlersuche.
chrische
-
static-Funktionen kann man immer ohne eine einzige Instanz einer Klasse ausführen. Das macht aber bei deinen Funktionen keinen Sinn, weshalb man sie nicht statisch macht.
-
Ich versteh noch nicht ganz zu was genau du es brauchst aber es könnte in diese Richtung gehen:
class foo { private: void bar_0() { cout << "bar_0();" << endl; } void bar_1() { cout << "bar_1();" << endl; } void bar_2() { cout << "bar_2();" << endl; } static void (foo::*pfunc[3])(); public: void call(int num) { (this->*pfunc[num])(); } foo() { } }; void (foo::*(foo::pfunc[3]))() = { &foo::bar_0, &foo::bar_1, &foo::bar_2 };Hoffe das stimmt so habs net getestet. Man sollte villeicht noch ein typedef verwenden.
-
Hallo
Erstmal danke für eure Hilfe. Da alles bei mir nicht geklappt hat, habe ich mich jetzt doch für die switch-Variante entschieden.
chrische
-
Hallo,
ich möchte die Antwort eines Touchscreens (über den I²C-Bus) mit einem Atmel
AtMega88-Controller auswerten. Ich verwende zum Programmieren den kostenlosen
AVR-GCC-Compiler.Der Touchscreen liefert je nach betätigtem Button einen 8-Bit Returncode zum
Prozessor (den Returncode vergebe ich im intelligenten Display selber). Die Auswertung habe ich mit IF-Anweisungen angefangen, da ich aber ca. 100 Returncodes auswerten muß, wird das verdammt umständlich.Wie schreibe ich ein Funktionsarray in C? So ganz klar ist mir das nicht. Habe auch bisher keine große Erfahrung mit solch "komplexen" Sachen.
Ich habe folgendes:
* Rückgabewert des Displays (z.B. 1...127)
* diverse Befehle, die bei den entsprechenden Rückgabewerten ausgeführt werden sollen.Vielen Dank im Voraus.
Martin