[C++] Problem mit überladener Member-Funktion

Sorry dass ich so lange nicht geantwortet habe aber ich hatte leider kaum Zeit. Werde mir jetzt erstmal wieder mehr Zeit dafür nehmen :D Schon fast 2 Wochen vergangen. Wie schnell doch die Zeit vergeht.

Das einzige was ich nicht weiß was es damit auf sich hat sind die virtuellen Methoden. Templates benutzt ich nie weil ich nicht genau weiß wofür. Polymorphie kenn ich natürlich.

Hab das jetzt mal versucht in meinen Code zu integrieren aber irgendwie mach ich da was falsch :(

Also hier noch mal der Code. Die karte.h hab ich mir jetzt mal gespart weil sie 1. hier nicht wichtig ist und 2. sich nicht geändert hat :lol:

Code:
//Claden.h

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)));
}

//laden.h

#ifndef _datei_
#define _datei

#include <StdIO.h>
#include <IO.h>
#include <FCntl.h>
#include <iostream>
#include <string>
#include <fstream>
#include <Claden.h>
#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 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, CallHolder pFunction);
	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, CallHolder pFunction)
{
	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);
	name(SParameters &p);
	SetField(SParameters &p);

	// Die Script Funktionen
};

inline Datei::Datei()
{
	m_NumCommands=1;	
};


int Datei::dread(char* fileName, Karte& karte)
{
	cout<<"Beginn der dread Methode"<<endl;
	
	Claden script(fileName);

	cout<<"Script Datei konnte erstellt werden !"<<endl;
	
	script.AddCommand("name", make_call( this, &Datei::name));
	script.AddCommand("SetField", make_call( this, &Datei::SetField));
	cout<<"Script SetField konnte erstellt werden !"<<endl;
	
	for(int i = 0; i <m_NumCommands;i++)
	{
		cout<<"Schleifendurchlauf Nr. "<<i<<endl;	
	}  
	
	cout<<"Ende der dread Methode"<<endl;
  
	return 1;

}
#endif

Tut mir leid dass ich hier so riesen Code-brocken poste aber ich weiß nicht wie ich sonst den Fehler ausmerzen kann außer euch zu fragen.

Die Fehlermeldung:
--------------------Konfiguration: maps - Win32 Release--------------------
Kompilierung läuft...
main.cpp
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\Claden.h(48) : error C2555: 'MethCall<T>::clone' : Neue Version der virtuellen Funktion unterscheidet sich von 'CallBase::clone' nur hinsichtlich des Ergebnistyps oder der Aufrufkonvention
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\Claden.h(6) : Siehe Deklaration von 'CallBase'
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\Claden.h(54) : Siehe Verweis auf Instantiierung der kompilierten Klassenvorlage 'MethCall<T>'
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(82) : error C2675: Unaerer Operator '!' : 'class CallHolder' definiert diesen Operator oder eine Konvertierung in einen fuer den vordefinierten Operator geeigneten Typ nicht
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(85) : error C2679: Binaerer Operator '=' : Kein Operator definiert, der einen rechtsseitigen Operator vom Typ 'class CallHolder' akzeptiert (oder keine geeignete Konvertierung moeglich)
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(140) : error C2785: 'class CallHolder __cdecl make_call(T *,void (__thiscall T::*)(struct SParameters &))' und '<unbekannt>' haben verschiedene Rueckgabetypen
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\Claden.h(57) : Siehe Deklaration von 'make_call'
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(141) : error C2785: 'class CallHolder __cdecl make_call(T *,void (__thiscall T::*)(struct SParameters &))' und '<unbekannt>' haben verschiedene Rueckgabetypen
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\Claden.h(57) : Siehe Deklaration von 'make_call'
Fehler beim Ausführen von cl.exe.

maps.exe - 5 Fehler, 0 Warnung(en)

Ich hoffe ihr könnt mir mal wieder helfen. Währe euch sehr dankbar. Hoffentlich hat es sich dann damit getan :D Hätte nicht gedacht dass das ganze sich so hinzieht.
 
Mach mal folgende Änderungen:


Code:
struct SCommand
{
	char acName[256];
	CallHolder pFunction;
};


Anscheinend kann deine Version vom Visual Studio keine kovarianten Rückgabetypen. (noch das 6er?)
Also das hier ändern:

Code:
template <class T>
class MethCall: public CallBase
{

........

   virtual CallBase* clone() const
   {
      return new MethCall( _o, _m);
   }
};


Dieser Operator muss noch dazu:

Code:
class CallHolder
{
public:
   bool operator!()
   {
      return _call.get() == 0;
   }

};




Hmm mich wundert jetzt, dass Du Polymorpie kennst, aber keine virtuellen Methoden ;) Virtuelle Methoden sorgen dafür, dass die richtige Methode der abgeleiteten Klasse aufgerufen wird, auch wenn Du nur einen Basisklassen-Zeiger hast.
 
Danke erstmal für die schnelle Antwort. Aber ich hab schon wieder n Fehler :(

Die Fehlermeldung:
--------------------Konfiguration: maps - Win32 Release--------------------
Kompilierung läuft...
main.cpp
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(140) : error C2784: 'class CallHolder __cdecl make_call(T *,void (__thiscall T::*)(struct SParameters &))' : Vorlagenargument fuer 'ueberladener Funktionstyp' von 'ueberladener Funktionstyp' konnte nicht h
ergeleitet werden
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(141) : error C2784: 'class CallHolder __cdecl make_call(T *,void (__thiscall T::*)(struct SParameters &))' : Vorlagenargument fuer 'ueberladener Funktionstyp' von 'ueberladener Funktionstyp' konnte nicht h
ergeleitet werden
Fehler beim Ausführen von cl.exe.

maps.exe - 2 Fehler, 0 Warnung(en)

Das sind diese beiden Zeilen:
script.AddCommand("name", make_call( this, name));
script.AddCommand("SetField", make_call( this, SetField));

Irgendwie mach ich was falsch. Bekomme nur noch Fehlermeldungen irgendwie :D
Übrigens hab ich wirklich den VS C++ 6. das war mal bei einem buch dabei.
 
daemon777 schrieb:
Das sind diese beiden Zeilen:
script.AddCommand("name", make_call( this, name));
script.AddCommand("SetField", make_call( this, SetField));

Es soll ja auch heißen:

script.AddCommand("name", make_call( this, &Datei::name));
script.AddCommand("SetField", make_call( this, &Datei::SetField));

Hab ich aber so hingeschrieben original :stock: :D :D
 
Das gab auch nen Fehler :D

--------------------Konfiguration: maps - Win32 Release--------------------
Kompilierung läuft...
main.cpp
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(141) : error C2785: 'class CallHolder __cdecl make_call(T *,void (__thiscall T::*)(struct SParameters &))' und '<unbekannt>' haben verschiedene Rueckgabetypen
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\Claden.h(61) : Siehe Deklaration von 'make_call'
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\laden.h(142) : error C2785: 'class CallHolder __cdecl make_call(T *,void (__thiscall T::*)(struct SParameters &))' und '<unbekannt>' haben verschiedene Rueckgabetypen
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\Claden.h(61) : Siehe Deklaration von 'make_call'
Fehler beim Ausführen von cl.exe.

maps.exe - 2 Fehler, 0 Warnung(en)
 
Ich glaub das einfachste ist es, wenn Du mir mal dein Projekt zur Verfügung stellst, sofern Du das willst :)
 
warum sollte ich nicht ?
1. hab ich nichts zu verbergen ( alles legal )
2. hab ich meinen ganzen code bereits gepostet :D
3. stell ich mich so blöd an dass ich es alleine nicht hinbekomme

ich hoffe mal das mit dem Anhängen funktioniert.

Ich hoffe mal der Code ist übersichtlich. Währe cool wenn du mir helfen könntest
 

Anhänge

So ich hab das mal bearbeitet. Du hast einfach das void vor den Funktionen vergessen.

Deine includes waren aber auch etwas grauenhaft :) Hab die mal angepasst. Nur Systemheader werden in spitzen Klammern <> inkludiert, deine eigenen in Anführungszeichen. ""

Ich hab außerdem mal die Implementierung in cpp Dateien ausgelagert. Schau's Dir einfach mal an ;)
 

Anhänge

Langsam krieg ich die Krise :D

--------------------Konfiguration: maps - Win32 Debug--------------------
Kompilierung läuft...
main.cpp
Linker-Vorgang läuft...
laden.obj : error LNK2001: Nichtaufgeloestes externes Symbol "public: void __thiscall Datei::SetField(struct SParameters &)" (?SetField@Datei@@QAEXAAUSParameters@@@Z)
laden.obj : error LNK2001: Nichtaufgeloestes externes Symbol "public: void __thiscall Datei::name(struct SParameters &)" (?name@Datei@@QAEXAAUSParameters@@@Z)
Debug/maps.exe : fatal error LNK1120: 2 unaufgeloeste externe Verweise
Fehler beim Ausführen von link.exe.

maps.exe - 3 Fehler, 0 Warnung(en)


Mit dem Code den du mir geschickt hast. Also ich versteh das echt nicht mehr. Überhaupt warum haben wir eine laden.cpp ? die wird nirgendwo inkludiert.
 
SetField und name sind doch auch noch nicht implementiert. Deshalb die Fehlermeldung vom Linker.

Natürlich wird die laden.cpp nirgendwo inkludiert. Sie enthält die Implementation von laden.h und wird später vom Linker zur Anwendung dazugelinkt. Ich glaube, du solltest dir mal das Prinzip von .h und .cpp Dateien nochmal anschauen :)
 
Ich vermute dann einfach mal das laden.cpp nicht im Workspace enthalten ist. Deswegen wird das file dann nicht mitkompiliert bzw. mitgelinkt.

MfG

Arnd
 
Ja danke. Es funktioniert ( zumindest vorläufig :D )

Ihr habt mir sehr weitergeholfen. Auch wenn ich im Moment noch nicht 100 %ig durchblicke welcher Teil des Codes was macht aber ich hoffe das kommt noch. wenn ich so weit bin mache ich weiter. Hoffentlich muss ich euch dann nicht wieder belästigen :p
 
Es hilft ungemein beim Verständnis von Code, wenn man mal wirklich jede Zeile mit dem Debugger durchsteppt (F11). Es ist manchmal erstaunlich wo man da landet :-).

MfG

Arnd
 
Zurück
Oben