Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden.
Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
[C++] Problem mit überladener Member-Funktion
- Ersteller daemon777
- Erstellt am
Hallo daemon777,
nur mal als Gedanke.
Eine Funktion die eine Zeile scannt und alle einzelnene Wörter in eine stl Liste stellt. D.h. es werden einfach alle Leerzeichen, Tabulatoren, ... entfernt.
Der erste Eintrag in dieser Liste beinhaltet dann das Kommandowort. Dieses Kommandowort wird dann in einer Tabelle gesucht. Diese Tabelle beinhaltet das Kommandowort und die dazugehörige Funktion/Methode die dazu aufgerufen wird.
Diese Kommandofunktion bekommt als Parameter die stl Liste mit den Parametern übergeben und kann diese dann auswerten.
Das ganze ist in Code relativ kurz, gut erweiterbar und übersichtlich.
Du brauchst:
- Eine Methode zum erstellen der Parameterliste.
- Eine Strukturdefinition
- und einen "Dreizeiler" um diese Tabelle zu parsen.
MfG
Arnd
nur mal als Gedanke.
Eine Funktion die eine Zeile scannt und alle einzelnene Wörter in eine stl Liste stellt. D.h. es werden einfach alle Leerzeichen, Tabulatoren, ... entfernt.
Der erste Eintrag in dieser Liste beinhaltet dann das Kommandowort. Dieses Kommandowort wird dann in einer Tabelle gesucht. Diese Tabelle beinhaltet das Kommandowort und die dazugehörige Funktion/Methode die dazu aufgerufen wird.
Diese Kommandofunktion bekommt als Parameter die stl Liste mit den Parametern übergeben und kann diese dann auswerten.
Das ganze ist in Code relativ kurz, gut erweiterbar und übersichtlich.
Du brauchst:
- Eine Methode zum erstellen der Parameterliste.
- Eine Strukturdefinition
- und einen "Dreizeiler" um diese Tabelle zu parsen.
MfG
Arnd
- Registriert
- Dez. 2003
- Beiträge
- 1.371
Cool danke 
7H3 N4C3R meinst du das gleiche ? ^^
Hab mir doch gedacht dass ihr noch einen eleganteren Weg kennt sonst hätte ich ja nicht gefragt
Und zu der Sache mit dem Code: Immer her damit
Was Strings angeht hab ich leider noch ziemlich nachholbedarf wie ihr seht
Denke ansonsten werde ich keine großen Probleme haben ( jedenfalls hoffe ich das )
7H3 N4C3R meinst du das gleiche ? ^^
Hab mir doch gedacht dass ihr noch einen eleganteren Weg kennt sonst hätte ich ja nicht gefragt
Und zu der Sache mit dem Code: Immer her damit
Was Strings angeht hab ich leider noch ziemlich nachholbedarf wie ihr seht
Mein Ansatz ist mal wieder ein Mischmasch aus C und C++ :-). Die Funktionsweise ist die selbe, nur die Realiserung in reinem C++ ist sicher noch eleganter aber auch schwieriger zu verstehen wenn man es noch nie gesehen hat.
Versuch Dich doch erst mal selber daran. An Hand der Beschreibung sollte es doch eigentlich kein Problem sein. Das einzige knifflige sehe ich in der Deklaration eines Funktionspointers :-).
MfG
Arnd
Versuch Dich doch erst mal selber daran. An Hand der Beschreibung sollte es doch eigentlich kein Problem sein. Das einzige knifflige sehe ich in der Deklaration eines Funktionspointers :-).
MfG
Arnd
- Registriert
- Dez. 2003
- Beiträge
- 1.371
Ich hab grad eine Fehlermeldung mit der ich nciht klar komme 
Und zwar geht es um einen unaufgelösten externen Verweis.
Hab auch versucht alles auszukommentieren was neu ist aber der Verweis geht nicht weg.
-------------------Konfiguration: maps - Win32 Release--------------------
Kompilierung läuft...
main.cpp
Linker-Vorgang läuft...
main.obj : error LNK2001: Nichtaufgeloestes externes Symbol "public: int __thiscall Datei::dread(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class Karte &)" (?dread@Datei@@QAEHV?$basic_string@DU?$char_trai
ts@D@std@@V?$allocator@D@2@@std@@AAVKarte@@@Z)
Release/maps.exe : fatal error LNK1120: 1 unaufgeloeste externe Verweise
Fehler beim Ausführen von link.exe.
maps.exe - 2 Fehler, 0 Warnung(en)
Code ist eigentlich der gleiche wie oben. Also ich bekomme die Fehlermeldung auch wenn ich den Code wieder "kürze".
Und zwar geht es um einen unaufgelösten externen Verweis.
Hab auch versucht alles auszukommentieren was neu ist aber der Verweis geht nicht weg.
-------------------Konfiguration: maps - Win32 Release--------------------
Kompilierung läuft...
main.cpp
Linker-Vorgang läuft...
main.obj : error LNK2001: Nichtaufgeloestes externes Symbol "public: int __thiscall Datei::dread(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class Karte &)" (?dread@Datei@@QAEHV?$basic_string@DU?$char_trai
ts@D@std@@V?$allocator@D@2@@std@@AAVKarte@@@Z)
Release/maps.exe : fatal error LNK1120: 1 unaufgeloeste externe Verweise
Fehler beim Ausführen von link.exe.
maps.exe - 2 Fehler, 0 Warnung(en)
Code ist eigentlich der gleiche wie oben. Also ich bekomme die Fehlermeldung auch wenn ich den Code wieder "kürze".
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
Alsooo, mal grundsätzlich zu unaufgelösten Verweisen (oder auf englisch: unresolved external):
Mal ein winziges Beispiel:
funktion1 wird hier mit einer Definition bekannt gemacht. funktion2 kann sie nun also aufrufen und der Compiler ist happy. Jetzt kommt aber der Linker und muss alle Objekt-Dateien zusammensetzen zu einer Exe (jede CPP-Datei wird zu einer Objekt-Datei kompiliert).
Nun merkt der Linker aber: "Hmm... funktion2 ruft funktion1 auf, ich suche sie mal in allen Objekt-Dateien, die ich so habe. Jetzt finde ich aber ich finde das Ding nirgendwo. Ich melde dem Programmierer also einen unaufgelösten Verweis."
Ich hoffe das hilft schonmal grundsätzlich zu dieser Fehlermeldung.
Warum die jetzt kommt, kann viele Gründe haben. Wenn man mit einem System arbeitet, dass makefiles hat, können z.B. die Abhängigkeiten veraltet sein und es wird nicht alles übersetzt. IDEs wie VisualStudio nehmen einem diese Arbeit normalerweise ab.
Viel häufiger passiert es aber, dass man z.B. vergessen hat, die Funktion zu implementieren. Oder aber, die Definition unterscheidet sich von der Deklaration. (Definition ist normalerweise das, was man in den Header schreibt und Deklaration das "Ausprogrammieren", das man in der CPP-Datei macht). Beispiel dafür:
In diesem Fall gibt es nur eine Implemenation für double, nicht aber für int. Der Aufruf von funktion1 mit int würde hier einen nicht aufgelösten externen Verweis ergeben.
Ich hoffe, das hilft dir bei der Lösung des Problems. Ansonsten hilf uns nochmal mit aktuellem Quellcode
Mal ein winziges Beispiel:
Code:
void funktion1(int);
void funktion2()
{
funktion1( 5);
}
funktion1 wird hier mit einer Definition bekannt gemacht. funktion2 kann sie nun also aufrufen und der Compiler ist happy. Jetzt kommt aber der Linker und muss alle Objekt-Dateien zusammensetzen zu einer Exe (jede CPP-Datei wird zu einer Objekt-Datei kompiliert).
Nun merkt der Linker aber: "Hmm... funktion2 ruft funktion1 auf, ich suche sie mal in allen Objekt-Dateien, die ich so habe. Jetzt finde ich aber ich finde das Ding nirgendwo. Ich melde dem Programmierer also einen unaufgelösten Verweis."
Ich hoffe das hilft schonmal grundsätzlich zu dieser Fehlermeldung.
Viel häufiger passiert es aber, dass man z.B. vergessen hat, die Funktion zu implementieren. Oder aber, die Definition unterscheidet sich von der Deklaration. (Definition ist normalerweise das, was man in den Header schreibt und Deklaration das "Ausprogrammieren", das man in der CPP-Datei macht). Beispiel dafür:
Code:
// test.h
void funktion1( int i);
// test.cpp
void funktion1( double i);
Ich hoffe, das hilft dir bei der Lösung des Problems. Ansonsten hilf uns nochmal mit aktuellem Quellcode
- Registriert
- Dez. 2003
- Beiträge
- 1.371
Damit hab ich jetzt den (die) Fehler gefunden.
War ja irgendwie auch klar das ich da fehler reinbaue wenn sich die Funktion 100 mal ändert die Klasse an sich aber nicht. Da waren ja Fehler drinn das gibts gar nicht
Danke auch für die Erklärung wir mir in Zukunft sicherlich noch oft weiterhelfen.
Hab bestimmt bald die nächste Frage zum Code
War ja irgendwie auch klar das ich da fehler reinbaue wenn sich die Funktion 100 mal ändert die Klasse an sich aber nicht. Da waren ja Fehler drinn das gibts gar nicht
Danke auch für die Erklärung wir mir in Zukunft sicherlich noch oft weiterhelfen.
Hab bestimmt bald die nächste Frage zum Code
- Registriert
- Dez. 2003
- Beiträge
- 1.371
So und schon komm ich wieder nicht weiter 
Ich hab mir gedacht so lange es sich um den gleichen Code handelt sollte das der Übersichtshalber auch in einem Thread stehen. Wenn ich falsch gedach hab bitte sagen
Und zwar geht es um den Funktionspointer. Ein bischen was hab ich schon zusammen bekommen allerdings bekomme ich eine Fehlermeldung dass der parameter nicht Konvertiert werden kann. Dürfte eigentlich kein allzu großer Fehler sein aber ich versteh die Sprache des Kompilers immer noch nicht so ganz
Hier ist mal der Code:
Fehlermeldung ist folgende:
--------------------Konfiguration: maps - Win32 Release--------------------
Kompilierung läuft...
main.cpp
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(152) : error C2664: 'AddCommand' : Konvertierung des Parameters 2 von 'void (struct SParameters &)' in 'void (__cdecl *)(struct SParameters &)' nicht moeglich
Keine Funktion mit diesem Namen im Gueltigkeitsbereich stimmt mit dem Zieltyp ueberein
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(153) : error C2664: 'AddCommand' : Konvertierung des Parameters 2 von 'void (struct SParameters &)' in 'void (__cdecl *)(struct SParameters &)' nicht moeglich
Keine Funktion mit diesem Namen im Gueltigkeitsbereich stimmt mit dem Zieltyp ueberein
Fehler beim Ausführen von cl.exe.
maps.exe - 2 Fehler, 0 Warnung(en)
Der Code ist jetzt leider etwas lang aber wenn ich Teile weglasse verberge ich möglicherweise den Fehler.
Hoffe ihr könnt mir mal wieder weiterhelfen.
Ich hab mir gedacht so lange es sich um den gleichen Code handelt sollte das der Übersichtshalber auch in einem Thread stehen. Wenn ich falsch gedach hab bitte sagen
Und zwar geht es um den Funktionspointer. Ein bischen was hab ich schon zusammen bekommen allerdings bekomme ich eine Fehlermeldung dass der parameter nicht Konvertiert werden kann. Dürfte eigentlich kein allzu großer Fehler sein aber ich versteh die Sprache des Kompilers immer noch nicht so ganz
Hier ist mal der Code:
Code:
#ifndef _datei_
#define _datei
#include <StdIO.h>
#include <IO.h>
#include <FCntl.h>
#include <iostream>
#include <string>
#include <fstream>
#include <karte.h>
using namespace std;
DWORD GetFileSize(char* pcFilename)
{
DWORD dwSize;
int iFile = open(pcFilename, O_BINARY | O_RDONLY);
dwSize = filelength(iFile);
close(iFile);
return dwSize;
}
struct SParameters
{
int iNumParameters;
int aiInteger[16];
float afFloat[16];
string aString[16];
};
struct SCommand
{
char acName[256];
void (* pFunction)(SParameters&);
};
class Claden
{
private:
char* m_pcScript;
int m_iScriptSize;
SCommand m_aCommand[1024];
int m_iNumCommands;
public:
Claden(char* filename);
~Claden();
void AddCommand(char* pcName, void (* pFunction)(SParameters&));
SCommand* FindCommand(char* pcName);
inline char* GetScript() {return m_pcScript;}
inline int GetScriptSize(){return m_iScriptSize;}
};
Claden::Claden(char* filename) : m_pcScript(NULL), m_iScriptSize(0), m_iNumCommands(0)
{
if(filename == NULL) return;
FILE* pFile = fopen(filename, "rb");
if(pFile != NULL)
{
DWORD dwFileSize = GetFileSize(pFile,NULL/*Ka was das hier soll*/);
m_pcScript=new char[dwFileSize];
ZeroMemory(m_pcScript, dwFileSize);
fread(m_pcScript, 1, dwFileSize, pFile);
fclose(pFile);
m_iScriptSize = (int)(dwFileSize);
}
}
Claden::~Claden()
{
delete m_pcScript;
}
void Claden::AddCommand(char* pcName, void (* pFunction)(SParameters&))
{
if(!pcName || !pFunction || m_iNumCommands >= 1024) return;
strcpy(m_aCommand[m_iNumCommands].acName, pcName);
m_aCommand[m_iNumCommands].pFunction = pFunction;
m_iNumCommands++;
}
SCommand* Claden::FindCommand(char* pcName)
{
if(!pcName) return NULL;
for(int i=0; i<m_iNumCommands; i++)
{
if(!strcmp(pcName, m_aCommand[i].acName))
{
return &m_aCommand[i];
}
}
return NULL;
}
class Datei
{
private:
std::string m_dateiname;
std::string m_levelname;
int m_NumCommands;
public:
inline Datei();
int dread(char* fileName, Karte& karte);
// Die Script Funktionen
inline void name(SParameters& p);
void SetField(SParameters& p);
};
inline Datei::Datei()
{
m_NumCommands=1;
};
inline void Datei::name(SParameters& p)
{
}
inline void Datei::SetField(SParameters& p)
{
}
int Datei::dread(char* fileName, Karte& karte)
{
Claden script(fileName);
for(int i = 0; i <m_NumCommands;i++)
{
script.AddCommand("name", name);
script.AddCommand("SetField", SetField);
}
return 1;
}
#endif
Fehlermeldung ist folgende:
--------------------Konfiguration: maps - Win32 Release--------------------
Kompilierung läuft...
main.cpp
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(152) : error C2664: 'AddCommand' : Konvertierung des Parameters 2 von 'void (struct SParameters &)' in 'void (__cdecl *)(struct SParameters &)' nicht moeglich
Keine Funktion mit diesem Namen im Gueltigkeitsbereich stimmt mit dem Zieltyp ueberein
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(153) : error C2664: 'AddCommand' : Konvertierung des Parameters 2 von 'void (struct SParameters &)' in 'void (__cdecl *)(struct SParameters &)' nicht moeglich
Keine Funktion mit diesem Namen im Gueltigkeitsbereich stimmt mit dem Zieltyp ueberein
Fehler beim Ausführen von cl.exe.
maps.exe - 2 Fehler, 0 Warnung(en)
Der Code ist jetzt leider etwas lang aber wenn ich Teile weglasse verberge ich möglicherweise den Fehler.
Hoffe ihr könnt mir mal wieder weiterhelfen.
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
Naja... du gehst gleich auf's ganze
Was Du da willst sind keine Funktions-Zeiger, sondern Methoden-Zeiger. Das ist ein wichtiger Unterschied.
Während eine Funktion frei aufgerufen werden kann, gehört zu einer Methode immer das dazugehörige Objekt! (Methoden operieren nur auf Daten von Objekten)
D.h., Du musst zuerst einen Methodenzeiger formen und dann zusätzlich im AddCommand noch das Objekt übergeben, von dem Du die Methode aufgerufen haben willst.
Methodenzeiger definiert man so:
Ich hoffe mal, ich hab die Syntax so freihand hinbekommen. Wenn nicht, meckern D:
Während eine Funktion frei aufgerufen werden kann, gehört zu einer Methode immer das dazugehörige Objekt! (Methoden operieren nur auf Daten von Objekten)
D.h., Du musst zuerst einen Methodenzeiger formen und dann zusätzlich im AddCommand noch das Objekt übergeben, von dem Du die Methode aufgerufen haben willst.
Methodenzeiger definiert man so:
Code:
class A
{
public:
A( int i) : i_(i) {}
void print() { std::cout << i_ << std::endl; }
void increment() { ++i_; }
private:
int i_;
};
int main()
{
A a1 (5);
A a2 (6);
A* pa1 = &a1;
typedef void (A::* Methode)();
Methode m = &A::print;
(a1.*m)(); // 5
(a2.*m)(); // 6
m = &A::increment;
(a1.*m)();
m = &A::print;
(pa1->*m)(); // 6
}
Ich hoffe mal, ich hab die Syntax so freihand hinbekommen. Wenn nicht, meckern D:
Hallo daemon777,
das Problem mit dem Objektzeiger kannst Du alternativ umgehen, wenn Du die Methode als static deklarierst. Dann wird kein Objekt benötigt.
Was mir auch aufgefallen ist, das einige Sicherheitsabfragen fehlen.
DWORD GetFileSize(
HANDLE hFile, // handle to file
LPDWORD lpFileSizeHigh // high-order word of file size
);
GetFileSize erwartet ein HANDLE und keinen FILE*. Es kann 0 zurück kommen und ein new mit 0 ist nicht wirklich gut. Der zweite Parameter von GetFileSize() ist übrigens für Files gedacht deren Länge 4GB übersteigt.
Du solltest daher schon Deine eigene Funktion verwenden. Die es ja auch gibt :-).
Allerdings wird das open nicht auf Fehler abgefragt! Und ein zweimaliges open auf das selbe File muss auch nicht unbedingt funktionieren.
Das hier ist auch nicht wirklich schön:
SCommand m_aCommand[1024];
Ich würde vorschlagen:
std::list<SCommand> m_ListOfCommands;
MfG
Arnd
das Problem mit dem Objektzeiger kannst Du alternativ umgehen, wenn Du die Methode als static deklarierst. Dann wird kein Objekt benötigt.
Was mir auch aufgefallen ist, das einige Sicherheitsabfragen fehlen.
DWORD GetFileSize(
HANDLE hFile, // handle to file
LPDWORD lpFileSizeHigh // high-order word of file size
);
GetFileSize erwartet ein HANDLE und keinen FILE*. Es kann 0 zurück kommen und ein new mit 0 ist nicht wirklich gut. Der zweite Parameter von GetFileSize() ist übrigens für Files gedacht deren Länge 4GB übersteigt.
Du solltest daher schon Deine eigene Funktion verwenden. Die es ja auch gibt :-).
Allerdings wird das open nicht auf Fehler abgefragt! Und ein zweimaliges open auf das selbe File muss auch nicht unbedingt funktionieren.
Das hier ist auch nicht wirklich schön:
SCommand m_aCommand[1024];
Ich würde vorschlagen:
std::list<SCommand> m_ListOfCommands;
MfG
Arnd
- Registriert
- Dez. 2003
- Beiträge
- 1.371
Irgendwie steh ich grad aufm Schlauch 
Will jetzt nicht den Code wieder zerhacken. gibt es denn eine einfache Lösung wie ich aus meinem Code einen funktionierenden formen kann ? Und noch mal ne allgemeinere Frage: Was bedeutet (__cdecl *) ?
Will jetzt nicht den Code wieder zerhacken. gibt es denn eine einfache Lösung wie ich aus meinem Code einen funktionierenden formen kann ? Und noch mal ne allgemeinere Frage: Was bedeutet (__cdecl *) ?
Versuch mal:
cdecl ist eine Aufrufkonvention, die festlegt wie Parameter auf dem Stack übergeben werden. Das spielt bei gemischter Verwendung von C und C++ eine Rolle.
MfG
Arnd
Code:
// Die Script Funktionen
static void name(SParameters& p);
static void SetField(SParameters& p);
cdecl ist eine Aufrufkonvention, die festlegt wie Parameter auf dem Stack übergeben werden. Das spielt bei gemischter Verwendung von C und C++ eine Rolle.
MfG
Arnd
- Registriert
- Dez. 2003
- Beiträge
- 1.371
Kompilieren und Linken ist jetzt fehlerfrei aber sobald eine Instanz der Claden Klasse erstellt wird stürtzt das Programm ab. Also bei der Zeile "Claden script(fileName);".
Das mit dem std::list<SCommand> m_ListOfCommands; hab ich jetzt noch nicht gemacht. Würde das helfen ? Wenn ich da std::list<SCommand> m_aCommand drauß mache muss ich dann im Code sonst noch was ändern oder funktioniert das dann wie bisher ?
Und überhaupt was heißt std::list<SCommand> ? Ich hab das bisher noch nie benutzt
Sorry wenn ich so viele Fragen habe aber ich bin im Moment ein wenig übermotiviert
Das mit dem std::list<SCommand> m_ListOfCommands; hab ich jetzt noch nicht gemacht. Würde das helfen ? Wenn ich da std::list<SCommand> m_aCommand drauß mache muss ich dann im Code sonst noch was ändern oder funktioniert das dann wie bisher ?
Und überhaupt was heißt std::list<SCommand> ? Ich hab das bisher noch nie benutzt
Sorry wenn ich so viele Fragen habe aber ich bin im Moment ein wenig übermotiviert
Hallo daemon777,
das das Programm jetzt linkt ist doch schon mal ein Schritt in die richtige Richtung :-).
Das static hat natürlich ein paar Konsequenzen, die auch beachtet werden müssen.
In einer static Methode bist Du zwar in der aktuellen Klasse, aber es ist kein Objekt vorhanden auf das Du zu zugreifen kannst.
D.h. Du brauchst eine Referenz auf das Objekt mit dem Du arbeiten willst. Wenn das viele verschiedene sind, machst es wahrscheinlich mehr Sinn den Ansatz von 7H3 N4C3R weiterzuverfolgen.
Wo das Programm genau abstürzt das verrät Dir am besten der Debugger.
Am einfachsten übergibst Du der statischen methode einen Pointer auf das Objekt mit der es arbeiten soll.
z.B:
Das std:list bedingt auch eine andere Handhabung. Schliesslich ist das eine Liste variabler Länge und kein statisches Array mehr:
Hinzufügen zur Liste:
Iterieren der Liste:
Löschen eines Eintrags:
Das ganze ist flexibel einsetzbar. Man muss wesentlich weniger Code zur Verwaltung schreiben. Und es wird nicht unnötig Platz verbraucht.
MfG
Arnd
das das Programm jetzt linkt ist doch schon mal ein Schritt in die richtige Richtung :-).
Das static hat natürlich ein paar Konsequenzen, die auch beachtet werden müssen.
In einer static Methode bist Du zwar in der aktuellen Klasse, aber es ist kein Objekt vorhanden auf das Du zu zugreifen kannst.
D.h. Du brauchst eine Referenz auf das Objekt mit dem Du arbeiten willst. Wenn das viele verschiedene sind, machst es wahrscheinlich mehr Sinn den Ansatz von 7H3 N4C3R weiterzuverfolgen.
Wo das Programm genau abstürzt das verrät Dir am besten der Debugger.
Am einfachsten übergibst Du der statischen methode einen Pointer auf das Objekt mit der es arbeiten soll.
z.B:
Code:
Datei::name(<Parameter>, <Referenz auf Objekt>);
Das std:list bedingt auch eine andere Handhabung. Schliesslich ist das eine Liste variabler Länge und kein statisches Array mehr:
Hinzufügen zur Liste:
Code:
std::list<CString> lListOfStrings;
lListOIfStrings.push_back( "Hallo Welt" );
lListOIfStrings.push_back( "Hallo Welt2" );
lListOIfStrings.push_back( "Hallo Welt3" );
Iterieren der Liste:
Code:
std::list<CString>::iterator lItem = lListofStrings.begin();
while( lItem != lListOfStrings.end() )
{
cout << *lItem << endl;
lItem++;
}
Löschen eines Eintrags:
Code:
long lCount = 0;
while( lItem != lListOfStrings.end() )
{
if( lCount == 1 )
{
lListOfStrings.erase( lItem );
break;
}
lItem++;
lCount++;
}
Das ganze ist flexibel einsetzbar. Man muss wesentlich weniger Code zur Verwaltung schreiben. Und es wird nicht unnötig Platz verbraucht.
MfG
Arnd
Zuletzt bearbeitet:
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
So, hab mir grad mal die Zeit genommen, das ganze auf Methodenzeiger umzustellen 
Das hier tust Du am besten in einen eigenen Header, so wie's da steht. Nur noch Includeguards einfügen.
In der eigentlichen Datei includest Du dann den Header und machst noch das hier:
Et voila... sollte gehen
Hab jetzt aber nur das Call-Gedöns getestet. Falls es nicht klappt, poste einfach nochmal den Code + Fehlermeldungen. Falls es Dich interessiert, wie das eigentlich genau funktioniert, frag auch nach 
Das hier tust Du am besten in einen eigenen Header, so wie's da steht. Nur noch Includeguards einfügen.
Code:
#include <memory>
struct SParameters;
class CallBase
{
public:
virtual void operator()( SParameters&) const = 0;
virtual CallBase* clone() const = 0;
virtual ~CallBase() throw() {}
};
class CallHolder
{
public:
CallHolder() {}
explicit CallHolder( std::auto_ptr<CallBase> call) : _call( call) {}
CallHolder( const CallHolder& other) : _call( other._call->clone())
{
}
CallHolder& operator=( const CallHolder& other)
{
CallHolder tmp( other);
_call = tmp._call;
return (*this);
}
void operator()( SParameters& params) const
{
(*_call)( params);
}
private:
std::auto_ptr<CallBase> _call;
};
template <class T>
class MethCall: public CallBase
{
public:
typedef T* ObjectPtr;
typedef void( T::* Method)( SParameters&);
MethCall( ObjectPtr o, Method m) : _o(o), _m(m) {}
virtual void operator() ( SParameters& params) const
{
(_o->*_m)( params);
}
virtual MethCall* clone() const
{
return new MethCall( _o, _m);
}
private:
ObjectPtr _o;
Method _m;
};
template <class T>
CallHolder make_call( T* o, void( T::* m)( SParameters&))
{
return CallHolder( std::auto_ptr<CallBase>( new MethCall<T>( o, m)));
}
In der eigentlichen Datei includest Du dann den Header und machst noch das hier:
Code:
struct SCommand
{
char acName[256];
CallHolder pFunction;
};
...
class Claden
{
...
// Signatur der Deklaration von AddCommand auch anpassen
void AddCommand(char* pcName, CallHolder pFunction);
...
};
...
int Datei::dread(char* fileName, Karte& karte)
{
Claden script(fileName);
for(int i = 0; i <m_NumCommands;i++)
{
script.AddCommand("name", make_call( this, &Datei::name));
script.AddCommand("SetField", make_call( this, &Datei::SetField));
}
return 1;
}
Et voila... sollte gehen
Zuletzt bearbeitet:
- Registriert
- Dez. 2003
- Beiträge
- 1.371
Cool danke für den Code 
Getestet hab ichs jetzt noch nicht aber ich werd bestimmt noch ein paar Fehler reinbauen
Erklährung währe nicht schlecht. Virtuelle Methoden und Templates hab ich nämlich auch noch nie benutzt.
Getestet hab ichs jetzt noch nicht aber ich werd bestimmt noch ein paar Fehler reinbauen
Erklährung währe nicht schlecht. Virtuelle Methoden und Templates hab ich nämlich auch noch nie benutzt.
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
Puh, also zumindest mit Polymorphie und virtuellen Methoden solltest Du dich schon ein klein wenig beschäftigt haben, sonst rede ich mir den Mund fusselig *gg* Und das Template da, hm im Prinzip gehts auch ohne. Der Code ist eh nur halb so generisch, wie er sein sollte. Nur dann wird das Verständnis noch schlimmer 
Ähnliche Themen
- Antworten
- 5
- Aufrufe
- 1.974
- Antworten
- 3
- Aufrufe
- 1.598
- Antworten
- 1
- Aufrufe
- 1.196