OO-Design

Deklariere doch die Funktion in der Klasse PersistAdapter auch virtual. In der Klasse PersistAdaptArtikel sollte die funktion weder deklariert noch definiert werden.
 
Jens Hibbeler hat gesagt.:
Hallo,

..vielleicht noch als Ergänzung:

Wenn ich die Methode in der zuletzt abgeleiteten Klasse nicht implementiere bekomme ich:
[Linker Fehler] Unresolved external 'PersistAdaptArtikel::ChangeAntwortHdl(const Link&, ArtikelPosition *)' referenced from O:\KUBIS\CLIENT\OBJ.32\PERSIST\ARTKLPO1.OBJ

Hallo,

die Info mit der kann man denke was anfangen...

Code:
class PersistAdaptArtikel : public PersistAdapter, public PersistierungsIntArtikel
{
   public :bool  bestandsAnfrage(Link & nAntwortHdl, ArtikelPosition *artP);
   public :Link  ChangeAntwortHdl  ( const Link&   neuerAntwortHdl, ArtikelPosition *artP);
};
Du deklarierst die Methode ChangeAntwortHdl aber implementierst sie nicht, das resultiert dann in einem Linkerfehler. Lass doch die Deklaration einfach weg:
Code:
class PersistAdaptArtikel : public PersistAdapter, public PersistierungsIntArtikel
{
   public :bool  bestandsAnfrage(Link & nAntwortHdl, ArtikelPosition *artP);
};


//edit
Aso:
Entferne ich zusätzlich die Deklaration in dem Header der Klasse gilt diese als Abstrakt.

Bist du dir denn dann sicher das du die Methode ChangeAntwortHdl in
PersistAdapter auch wirklich überschreibst?
Wie schaut es aus mit der Klasse PersistierungsIntArtikel erbt diese auch von
deinem Interface und wenn ja überschreibst du dort auch die Methode
ChangeAntwortHdl?

Gruß

RedWing
 
Zuletzt bearbeitet:
Hallo schau dir auch bitte nochmal das Beispiel an. Und vergleichs mit deinem
Design:
Code:
#include <iostream>

using namespace std;

class A{
    public:
        virtual void foo() = 0;
};

class B : public A{
    public:
        void foo(){
            cout << "Fooing..." << endl;
        }
};

class C : public B{
};

int main(){
    A* c = new C();
    c->foo();
    delete c;
}
So sollte es funktionieren.

Gruß

RedWing
 
In dem Beispiel ist 'c' aber von Typ A*. Dann gibt es keinen Zugriff auf Member von C ohne Typecast. Eigentlich sollte es auch mit
Code:
C* c = new C();
gehen
 
jokey2 hat gesagt.:
In dem Beispiel ist 'c' aber von Typ A*. Dann gibt es keinen Zugriff auf Member von C ohne Typecast. Eigentlich sollte es auch mit
Code:
C* c = new C();
gehen

Hallo das kommt ganz auf das Problem an
Der Sinn von A* c = new C(); ist das erreichen der Polymorphie.
Und die Funktion wird durch das Schluesselwort virtual schon richtig weitergeleitet...
Zugriffe auf Members macht man eh nur über Methoden, und wenn diese Virtual
sind passt es ja... Wenn man es nach deinem Vorschlag macht dann macht auch
das virtual keinen Sinn mehr und man kann gleich normale Methoden
implenetieren...
Und falls doch mal ein cast notwendig ist dann castet man halt mit dem
dynamic_cast Operator...

Gruß

RedWing
 
Zuletzt bearbeitet:
Das virtual braucht man auf jeden Fall, da die Methode der Basisklasse abstrakt ist. Das geht nur mit virtuellen Funktionen.
Aber Zugriff auf Member von C (ich meine, Member, die nur in C deklariert sind, nicht in A oder B) hat man so nicht.
 
jokey2 hat gesagt.:
Aber Zugriff auf Member von C (ich meine, Member, die nur in C deklariert sind, nicht in A oder B) hat man so nicht.

RedWing hat gesagt.:
Und falls doch mal ein cast notwendig ist dann castet man halt mit dem
dynamic_cast Operator...

Wenn man es nach deinem Vorschlag macht dann macht auch
das virtual keinen Sinn mehr und man kann gleich normale Methoden
implenetieren...

Das war auf die Polymorphie bezogen. In deinem Bsp ist dein Objekt ( c ) nicht Polymorph. In meinem schon und so kann
man den virtual Mechanismus in vollen Zuegen aureizen... Das ist ja mit der eigentliche Sinn einer abstrakten
Basisklasse.


Gruß

RedWing
 
Zuletzt bearbeitet:
Hallo,

ich habe das Problem jetzt identifiziert. Eigentlich wollte ich hier ein kleines Klassendiagramm darstellen, aber das scheint sich nciht einbinden zu lassen. Deshalb die Darstellung als Text:

Code:
Interface A<-----Klasse B
   n                 n
   |                  |
   |                  |
Interface C<-------Klasse D

Also Interface Aimplementiert pure virtuelle Memberfunktionen die von der Klasse B realisiert werden.
Interface C erweitert Klasse a durch Vererbung und implementiert ebenfalls pure virtuelle Memberfunktionen, die von der Klasse D realisiert werden.
Klasse D erweitert die Klasse B durch Vererbung.

Jetzt nehmen wir mal an, die Klasse B wäre nicht existent.
Der Compiler schaut in Klasse A nach und sieht ah, virtuelle Memberfunktionen. Sieht als nächstes ahja, Klasse C erweitert Klasse A um weitere spezialisierte virtuelle Memberfunktionen.
Nun gelangt er zur Klasse D und sieht: "Diese klasse ist nicht mehr abstrakt und muss alle Memberfunktionen implementieren".

Ergänzt man nun Klasse B erkennt der Kompiler nicht, dass durch die Vererbung der Methoden, die in Klasse B schon implementiert sind, diese nicht in Klasse D wiederum implementiert werden müssen.

Das scheint aber allgemein so zu sein, das Vererbung bei virtuellen Memeberfunktionen nicht als Implementierung gilt (jedenfalls beim Borland Compiler).

Ich habe gestern auch alles mögliche probiert (try and error) -da geht nichts...

Also nehme ich jetzt die Lösung, dass Klasse D einfach in deren Methoden die Methoden der Klasse D aufruft.

Ich muss sagen, dass ich das etwas entäuschend finde, da in anderen Programmiersprachen so etwas gehen würde. Ich würde auch fast sagen, dass es am Borland Compiler liegt. So etwas ist eigentlich kein kompliziertes Design, gehört zu den Basiscs, da es nur eine Abwandlung des Adapter Musters ist, und sollte für jeden Compiler kein Hindernis darstellen. Speziell bei einem, der lange Zeit hatte zu reifen...

Danke nochmal für Eure Antworten,

Jens
 
Zurück