Indy und Vererbung
-
Hallo miteinander,
ich tüftel gerade an einer Sache rum bei der es um die Indy-Komponenten(Version 9) geht.
Ich setze die FTP-Komponente TIdFtp öfters mal ein und habe damit an und für sich keine großen Probleme.
Ich habe mir nun Funktionen geschrieben die Verzeichnisse rekursiv löschen bzw. kopieren können. Diese funktionieren auch soweit wenn ich ein globales TIdFtp-Objektim Programm habe und mit diesem arbeite.
Ich wollte nun eine eigene Klasse machen die die Elemente von TIdFtp erben und meine beiden Funktionen hinzufügen.
Die Definition sieht folgendermaßen aus:
class MyIdFTP : public TIdFTP { public: void __fastcall FTPCopyDirectoryStructure(AnsiString DirToCopy); void __fastcall DeleteDirectory(AnsiString DirToDelete); };
Kompilieren tut das soweit auch, es gibt dann allerdings wenn ich ein Objekt von MyIdFtp erzeugen will bricht das Übersetzen ab:
int main(int argc, char* argv[]) { MyIdFTP *FTPClient = new MyIdFTP(NULL); delete FTPClient; return 0; }
[C++ Fehler] main.cpp(13): E2125 Compiler konnte Standardkonstruktor nicht für die Klasse 'MyIdFTP' generieren
Ich habe jetzt schon eine ganze Weile experimentiert und diverse Konstruktoren in meiner Klasse ausprobiert und alle möglichen Sorten Meldungen(Compilerfehler, Linkerfehler) bekommen. Ich muss sagen ich habe mit Vererbung und Co bisher wenig gemacht und bin in diesem Fall etwas ratlos...
Ich hoffe ich habe mich halbwegs verständlich ausgedrückt und jemand von euch kann mir auf die Sprünge helfen.
Vielen Dank schon Mal.
Gruß
Herdi
-
hast du es auch in der header-datei setehn??
#include ....
-
Hi,
// *.h //--------------------------------------------------------------------------- class MyIdFTP : public TIdFTP { public: void __fastcall FTPCopyDirectoryStructure(AnsiString DirToCopy); void __fastcall DeleteDirectory(AnsiString DirToDelete); //Konstruktor __fastcall MyIdFTP(TComponent* Owner); } //--------------------------------------------------------------------------- //*.cpp __fastcall MyIdFTP::MyIdFTP(TComponent* Owner) : TIdFTP(Owner){}
Das ist ein Standard-Konstruktor.
mfg
kpeter
-
Hallo danke schon Mal,
so hatte ich es vorhin sogar schon mal probiert. Ich erhalte dann immer die folgende Linker-Meldung:
[Linker Fehler] Error: Ungelöste externe '__fastcall Idtcpclient::TIdTCPClient::SetPortA(const int)' referenziert von C:\DOKUMENTE UND EINSTELLUNGEN\HERDI\DESKTOP\UPDATE UPLOAD\DEBUG_BUILD\FTP_FUNCTIONS.OBJ
Meine Klasse ist in ftp_functions.cpp/.h enthalten...
Wenn ich anstatt meiner MyIdFTP-Klasse eine "normale" TIdFTP-Klasse instanziere erhalte ich die Meldung nicht ohne es funktioniert auch normal...
Ich hoffe das bekommen wir vollends hin
Viele Grüße
Herdi
-
Hi,
steht doch in der Linkermeldung :
TIdTCPClient::SetPortA
Hast du schon/noch anderen Code in der Klassenableitung?
Wie erstellst du die Instanz?mfg
kpeter
-
Hi,
wie das so ist im Leben;
die Methode SetPort muss schon in der Klassenableitung stehen. Nach folgendem Code läuft der
Linker ohne Fehler durch:(Meine Klasse heisst etwas anders)
*.h
class TMyIdFTP : public TIdFTP { private: Word FPort; virtual void __fastcall SetPort(const System::Word AValue); public: __property System::Word Port = {read=FPort, write=SetPort, nodefault}; //void __fastcall FTPCopyDirectoryStructure(AnsiString DirToCopy); //void __fastcall DeleteDirectory(AnsiString DirToDelete); //Konstruktor __fastcall TMyIdFTP(TComponent* Owner); }; //--------------------------------------------------------------------------- // Das Formular wird um einen Zeiger und einen Destruktor ergänzt: class TForm1 : public TForm { __published: // IDE-verwaltete Komponenten private: TMyIdFTP *MyFTP; public: // Benutzer Deklarationen __fastcall TForm1(TComponent* Owner); __fastcall ~TForm1(void); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif
*.cpp
__fastcall TMyIdFTP::TMyIdFTP(TComponent* Owner) : TIdFTP(Owner){} void __fastcall TMyIdFTP::SetPort(const System::Word AValue) { if( AValue != FPort) FPort = AValue; } //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { MyFTP = new TMyIdFTP(this); // Instanz erzeugen } //--------------------------------------------------------------------------- __fastcall TForm1::~TForm1() { delete MyFTP; // Instanz löschen }
Tipp: wenn du nicht sicher bist, welche hpp gebraucht werden, lege eine TIdFTP-Kompo aufs Formular
und lösche sie wieder. Die hpp-Einträge bleiben.kpeter
-
Hi kpeter,
ich danke dir mal recht herzlich. Ich muss mir das erst mal zu Gemüte führen und versuchen zu verstehen was da passiert.
Leider sind die Indy-Komponenten bei der Turbo-C++-Explorer-Ausführung nicht auf der Komponentenpalette zu finden. Ich komm aber im allgemeinen auch so ganz gut zurecht. Prinzipiell füge ich diese halt von Hand so ein wie in deinem Beispiel. Mit Klassenableitungen hatte ich bisher noch nicht soviel zu tun. Zumindest waren diese Fälle dann einfach zu durchschauen.
Ich versteh gerade nicht ganz wieso ich in meiner Klassenableitung diese SetPort-Funktion brauche. Die Basisklasse von der ich ableite müsste diese ja schon haben? Die TIdFTP ist doch selbst wiederum von der TIdTCPClient abgeleitet? Oder bin ich auf dem falschen Dampfer? Wie bzw. wo weiß ich her das die SetPort-Funktion genau so auszusehen hat wie in deinem Beispiel?
Ich wünsch mal einen schönen Abend. Danke nochmals.
Gruß
Herdi
-
herdi schrieb:
Ich versteh gerade nicht ganz wieso ich in meiner Klassenableitung diese SetPort-Funktion brauche. Die Basisklasse von der ich ableite müsste diese ja schon haben?
Ja, hat sie auch, deshalb in meinem Posting davor die Frage, ob du bereits Code für diese Methode geschrieben
hast, und diese im Header nicht deklariert war. Dann hab ich die Klasse selbst im BCB2009 abgeleitet, und siehe da, auch mein Linker hat denselben Fehler geworfen.herdi schrieb:
Wie bzw. wo weiß ich her das die SetPort-Funktion genau so auszusehen hat wie in deinem Beispiel?
Hm, hab in der Pascaldatei idTCPClient.pas nachgeschaut; demnach wäre richtiger in SetPort:
void __fastcall TMyIdFTP::SetPort(const System::Word AValue) { FPort = AValue; if (IOHandler != NULL) { IOHandler->Port = AValue; } }
Na, teste mal durch.
Bis dann
kpeter
-
Hab mich heute früh mal ein wenig mit deinen Beispielen beschäftigt und es hat dann auch alles recht zügig wie gewünscht funktioniert. Meine abgeleitete Klasse mit meinen zusätzlich Funktionen funzt einwandfrei.
Ich habe bei der SetPort-Funktion im Prinzip deine erste Variante drin:
void __fastcall MyIdFTP::SetPort(const int Value){ if( Value != FPort) FPort = Value; }
Die letzte Variante tut bei mir nicht, da IOHandler irgendwie keine Variable "Port" besitzt...
Aber wie gesagt. Jetzt klappts. Danke nochmal.
Gruß
Herdi