PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C++/Delphi]: Abstrakte Klassen unterschied


pajofego
2006-11-06, 22:26:22
Hallo miteinander,

ich mal wieder und meine Versuche mir das C++ beizubringen.

Ich habe eine Basisklasse(abstrakte Klasse), in der steht da jetzt nicht viel drin.


template <class T>
class clClass
{
protected:
virtual void Init(const T& value) = 0;
virtual void Delete() = 0;
virtual void CopyValues(const clClass<T>& scr) = 0;
public:
clClass(void){};
virtual ~clClass(void){};
virtual const T& operator[](int i) const = 0;
};



Von dieser Klasse erbe ich jetzt folgende. Hier nur die Methode, mit der ich das Problem habe:


#include "clClass.h"

template <class T>
class clVector : public clClass<T>
{
protected:
//...mehr code
virtual void CopyValues(const clVector<T>& scr)
{
#ifdef _DEBUG
cout << "Laenge des Vektors: " << scr.GetLength() << endl;
#endif
if(m_iLength == scr.GetLength())
for(int i = 0; i<m_iLength; i++)
m_pVector[i] = scr[i];
else
{
cerr << "Vektorlaenge stimmen nicht ueberein!" << endl;
exit(1);
}
};
public:
//... mehr code
};



Versuche ich das ganze zu compilieren, bekomme folgende Fehlermeldung:

Fehler 1 error C2259: 'clVector<T>': Instanz von abstrakter Klasse kann nicht erstellt werden c:\eigene dateien\vspr2005\noc_2d\noc_2d\noc_2d.cpp 18

Aus meiner Delphizeit :biggrin: konnte ich soetwas wie das hier problemlos compilieren:


unit Unit1;

interface
type
myclass1 = class (Tobject)
protected
procedure mymethod(const val : myclass1); virtual; abstract;
end;
myclass2 = class(myclass1)
public
procedure mymethod(const val : myclass2);virtual;
end;

implementation

uses Windows;
{ myclass2 }

procedure myclass2.mymethod(const val: myclass2);
begin
writeln('Hello...!');
readln;
end;

end.


Jetzt meine Frage. Ich habe in delphi in der übergeordneten Klasse (myclass1) eine Methode (mymethod) als abstrakt definiert mit dem const Parameter vom Datentyp (myclass1). Die Klasse (myclass2), die von myclass 1 erbt beinhaltet die gleiche methode mit dem Parameter vom Typ myclass2. Ich meine jetzt - bis auf den Umstand, dass ich eine Template Klasse in C++ darstellen möchte - den gleichen Konstrukt in Delphi aufgebaut zu haben wie in C++. Daher meine Ratlosigkeit wieso Delphi den o.g. Code compiliert, aber C++ mit o.g. Fehlermeldung aussteigt. Hat jemand eine Erklärung für mich?

Danke und viele Grüße

pajofego

Coda
2006-11-06, 22:33:37
Hast du auch wirklich alle Funktionen überladen, die als abstrakt (=0) markiert waren?

Ansonsten gehts nicht.

pajofego
2006-11-06, 22:51:05
Hast du auch wirklich alle Funktionen überladen, die als abstrakt (=0) markiert waren?

Ansonsten gehts nicht.

Ich meine schon...ich habe mal in der abstrakten Basisklasse clClass und dann in der geerbten die Methode CopyValues auskommentiert. Da klappt die Compilierung problemlos. Ich kann auch eine Instanz von clVector erstellen.

Was auch geht, ist wohl die Umwandlung von


virtual void CopyValues(const clVector<T>& scr)

in

virtual void CopyValues(const clClass<T>& scr)



nur da meckert er bei dem Aufruf von "scr.GetLength()" das er GetLength() nicht kennt...klar ist ja auch nicht in clClass definiert. Ziel war es zu testen ob er sich am Datentyp von scr (clVector) stört, was ich aber ehrlich gesagt nicht ganz verstehe.

Gast
2006-11-06, 23:05:03
Um sowas zu lernen lässt man am Besten die Finger von Templates.
Dort wird nämlich meistens erst gemeckert, wenn man Methoden wirklich nutzt.

Zu dem anderen Problem:
virtual void CopyValues(const clVector<T>& scr)
ist nunmal nicht
virtual void CopyValues(const clClass<T>& scr)
weil eine anderen Argumentsignatur vorliegt.

Wenn du die 2. Methode nicht in der abgeleiteten Klasse implementierst, existiert sie weiterhin als abstrakte Methode, was dann auch zu einer abstrakten Klasse führt, die nicht instanziert werden kann.

pajofego
2006-11-06, 23:12:46
Um sowas zu lernen lässt man am Besten die Finger von Templates.
Dort wird nämlich meistens erst gemeckert, wenn man Methoden wirklich nutzt.

Zu dem anderen Problem:
virtual void CopyValues(const clVector<T>& scr)
ist nunmal nicht
virtual void CopyValues(const clClass<T>& scr)
weil eine anderen Argumentsignatur vorliegt.

Wenn du die 2. Methode nicht in der abgeleiteten Klasse implementierst, existiert sie weiterhin als abstrakte Methode, was dann auch zu einer abstrakten Klasse führt, die nicht instanziert werden kann.

Das war eigentlich meine Vermutung, bzw. die Frage obs nun einmal eine templatespez. Problem sei? Denn sonst verstehe ich nicht wieso der Delphicompiler o.g. Konstrukt akzeptiert und der C++ nicht. Stört der sich daran, dass er den Datentyp noch nicht kennt? :confused:

Ergo, lasse ich das ganze Zeug mit Template weg, müsste es dann gehen?

Gast
2006-11-06, 23:24:53
Ergo, lasse ich das ganze Zeug mit Template weg, müsste es dann gehen?
Nein es ist kein templatespezifisches Problem. Templates sind nur für C++ Anfänger problematisch, da man u.U. erst sehr spät auf Fehler hingewiesen wird und das Debuggen nicht unbedingt immer unproblematisch ist.

Mit einem anderen Argument überlädst du die Methode. D.h. du erzeugst eine weitere Methode, die aufgerufen wird, wenn man einen speziellen Argumenttyp übergibt.
Bei Delphi muss man (afaik) Methoden explizit mit dem Keyword "overload" überladen. Ansonsten überschreibt man die Methode einfach komplett.

pajofego
2006-11-06, 23:49:35
Nein es ist kein templatespezifisches Problem. Templates sind nur für C++ Anfänger problematisch, da man u.U. erst sehr spät auf Fehler hingewiesen wird und das Debuggen nicht unbedingt immer unproblematisch ist.

Mit einem anderen Argument überlädst du die Methode. D.h. du erzeugst eine weitere Methode, die aufgerufen wird, wenn man einen speziellen Argumenttyp übergibt.
Bei Delphi muss man (afaik) Methoden explizit mit dem Keyword "overload" überladen. Ansonsten überschreibt man die Methode einfach komplett.

ah...jetzt dämmerts langsam: :rolleyes:

Unabhängig von meinem Problem - da erscheint mir die Definition von der o.g. Methode nicht mehr sinnvoll - wie baue ich denn eigentlich in C++ so ein Gerüst wie in Delphi?


type
T1 = class(TObject)
procedure Test(I: Integer); overload; virtual;
end;

T2 = class(T1)
procedure Test(S: string); reintroduce; overload;
end;
...

SomeObject := T2.Create;
SomeObject.Test('Hello!'); // Aufruf von T2.Test
SomeObject.Test(7); // Aufruf von T1.Test

Xmas
2006-11-07, 01:19:32
class T1 {
public:
void Test(int i) {}
};
class T2 : public T1 {
public:
void Test(char* s) {}
};

int main()
{
T2 SomeObject;
T2.Test("Hello!");
T2.Test(7);
}
virtual ist bei diesem Beispiel nicht mal notwendig weil keine Methode überschrieben wird, nur überladen.

Dein Problem ist lediglich dass du clClass<T>::CopyValues(const clClass<T>& scr) nicht definierst. clVector<T>::CopyValues(const clVector<T>& scr) überlädt diese Methode ja lediglich, existiert also parallel, genau so als hätte die Methode einen ganz anderen Namen.