tutorials.de Buch-Aktion 05/2012
ERLEDIGT
JA
ANTWORTEN
6
ZUGRIFFE
9730
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Jens Hibbeler Jens Hibbeler ist offline Mitglied Bronze
    Registriert seit
    Oct 2005
    Beiträge
    32
    Hallo,

    ich bin gerade dabei C++ zu lernen und versuche zu begreifen wie Interfaces in dieser Sprache definiert und benutzt werden. Jedoch bin ich bis jetzt kläglich gescheitert. D.h. ich sehe meinen Fehler einfach nicht.
    Angenommen ich habe die Klasse PersistierungsIntArtikel, die das Interface mit Hilfe von virtuellen Funktionen abbildet (abstrakte Klasse mit Funtkionen wie: virtual void tuWas(void) =0. Dann habe ich noch die Klasse PersistIntAdapt Artikel, die das Interface durch Vererbung implementiert.
    Doch wie rufe ich diese auf? Ich komme aus der Java Welt und bin da anscheinend etwa verwirrt.
    Hier ein Beispiel mit Code.

    Die Header Datei des Interfaces:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    #ifndef PersisiterungsIntArtikel_h
    #define PersisiterungsIntArtikel_h
    #include <vcl.h>
     
    class PersistierungsIntArtikel 
    {
     
    public:
            virtual AnsiString Reserviere(AnsiString text) =0 ; 
     
    };
    #endif

    ----------------------------------------------------------------------------------------------------

    Die Header Datei der Datei, die das Interface implementiert:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    #ifndef PersistIntAdaptArtikel_h
    #define PersistIntAdaptArtikel_h
    #include "PersistierungsIntArtikel.h"
    #include <vcl.h>
     
    class PersistIntAdaptArtikel : PersistierungsIntArtikel {
             public: 
                    AnsiString  Reserviere(AnsiString text);
    };
    #endif

    ----------------------------------------------------------------------------------------------------

    Die zugehörige C++ Datei

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    #include "PersistierungsIntArtikel.h"
    #include "PersistIntAdaptArtikel.h"
    #include <vcl.h>
     
    AnsiString PersistIntAdaptArtikel::Reserviere(AnsiString text)
    {
            //...tu irgendwas...
            return "rueckgabe";
    }

    -----------------------------------------------------------------------------------------------------

    Nun wird interessant. Wie spreche ich nun die Klasse PersistIntAdaptArtikel über das Interface PersistierungsIntArtikel an? Vielleicht habe ich da was mit den Zeigern nicht verstanden? Muss ich den "new" Operator benutzen? Oder ist das Überschreiben der Methode in dem Header der Klasse PersistIntAdaptArtikel schon falsch? Warum muss ich beim Überschreiben die Klasse des Interfaces angeben?

    So geht das Aufrufen der Klasse jedenfalls nicht:

    Code :
    1
    2
    3
    4
    5
    
    PersistierungsIntArtikel pIntA;
     
    PersistIntAdaptArtikel *pIAA=&pIntA;
     
    piAA->Reserviere("Text");


    Könnte mir jemand helfen und einen Tip geben? Ich bin da etwas überfordert.

    Viele Grüße,

    Jens Hibbeler
     

  2. #2
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Hi.

    Du kannst keine Instanzen von abstrakten Klassen (Klassen mit rein virtuellen Funktionen) bilden. (erste Zeile in deinem letzten Codeschnipsel)

    Code :
    1
    2
    3
    4
    5
    6
    7
    
    PersistIntAdaptArtikel IAA;
     
    PersistierungsIntArtikel& IntA = IAA;
    PersistierungsIntArtikel* pIntA = &IAA;
     
    IntA.Reserviere("Text");
    pIntA->Reserviere("Text");

    Gruß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  3. #3
    Avatar von CodeFatal
    CodeFatal CodeFatal ist offline Mitglied Platin
    Registriert seit
    Oct 2004
    Beiträge
    509
    Moin,

    Der Fehler liegt hier
    Code :
    1
    2
    3
    4
    5
    
    PersistierungsIntArtikel pIntA;
     
    PersistIntAdaptArtikel *pIAA=&pIntA;
     
    piAA->Reserviere("Text");
    Funkionieren müsste es mit
    Code :
    1
    2
    3
    4
    5
    
    PersistIntAdaptArtikel *pIAA=new PersistIntAdaptArtikel;//Klasse anlegen
     
    piAA->Reserviere("Text");//Klasse benutzen
     
    delete pIAA;//Speicher freigeben nicht vergessen.
    Durch die Vererbung werden die richtigen Stukturen aus der Basis klasse automatisch genutzt. Du hast da oben eine Basisklasse angelegt - die übrigens die Funktion Reserviere nicht hat, weil nicht implementiert - und anschliessend versucht das auf die Kind-Klasse umzumünzen. Man könnte höchstens was der Art
    Code :
    1
    
    PersistierungsIntArtikel *pIntA = (PersistierungsIntArtikel *) piAA
    machen. Das nennt man CAST und , da gilt: Jede abgeleitete Klasse ist auch eine BasisKlasse aber eine Basisklasse ist keine Abgeleitete Klasse.

    Hoffe das hilft weiter...

    Gruss Michael
     
    Grüß die Welt, dann grüßt sie dich!

    Keine Panik, die Titanic ist schon gesunken!

  4. #4
    Jens Hibbeler Jens Hibbeler ist offline Mitglied Bronze
    Registriert seit
    Oct 2005
    Beiträge
    32
    Hi,

    das hat mir sehr geholfen! Danke!
    Ich dachte ich müsste das Interface ähnlich wie in Java ansprechen:

    Code :
    1
    
    Interface meinInterface=new KlasseDieDasInterfaceImplementiert();

    Das ich die virtuelle Methode in dem Header der von dem Interface abgeleiteten Klasse noch einmal definieren muss ist korrekt? Ich dachte durch Vererbung besitzt diese Klasse dann automatisch diese Methode? Oder ist das gerade der Klou?

    Viele Grüße,

    Jens
     

  5. #5
    Avatar von CodeFatal
    CodeFatal CodeFatal ist offline Mitglied Platin
    Registriert seit
    Oct 2004
    Beiträge
    509
    Virtuelle Funktionen sind nur Deklariert nicht aber Definiert.
    Soll heissen: Die BasisKlasse besteht auf der Funktion programmiert diese aber nicht aus

    Header BasisKlasse->Eintrag
    CPP BasisKlasse->Kein Eintrag

    Header AbgelKlasse->Kein Eintrag
    CPP AbgelKlasse->Eintrag

    Hab das zumindest so in Erinnerung. Schon lang her, das ich das nutzen durfte.

    Hier ist noch was falsch:
    Code :
    1
    
    Interface meinInterface=new KlasseDieDasInterfaceImplementiert();

    Interface != KlasseDieDasInterfaceImplementiert

    Da sollte der Compiler böse werden

    Richtig ist:
    Code :
    1
    
    KlasseDieDasInterfaceImplementiert meinInterface=new KlasseDieDasInterfaceImplementiert;

    Im Prinzip kannst du die Basisklasse ganz vergessen, wenn einmal die AbgeleiteteKlasse implementiert ist.

    Gruss Michael
     
    Grüß die Welt, dann grüßt sie dich!

    Keine Panik, die Titanic ist schon gesunken!

  6. #6
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Zitat Zitat von Jens Hibbeler
    Ich dachte ich müsste das Interface ähnlich wie in Java ansprechen:

    Code :
    1
    
    Interface meinInterface=new KlasseDieDasInterfaceImplementiert();
    In Java sind ja alle Variablen Referenzen (außer die primitiven Typen byte, char, int usw.). Das ist in C++ nicht so und wenn du schreibst
    Code :
    1
    
    MeineKlasse obj;
    dann wird automatisch ein Instanz der entsprechenden Klasse erstellt.

    In C++ wird halt extra unterschieden zwischen "normalen" Variablen, Referenzen und Pointern.

    Zitat Zitat von Jens Hibbeler
    Das ich die virtuelle Methode in dem Header der von dem Interface abgeleiteten Klasse noch einmal definieren muss ist korrekt? Ich dachte durch Vererbung besitzt diese Klasse dann automatisch diese Methode? Oder ist das gerade der Klou?
    Also erstmal hast du die Methode in dem Header ja gar nicht definiert, sondern nur deklariert. Die Deklaration ist notwendig da du dem Compiler mitteilen mußt das du jetzt die rein virtuelle Funktion der Basisklasse implementieren wirst (es gibt halt keine syntaktische Unterscheidung von Interface und Implementierung wie in Java (abstract class bzw. class / interface und implements). Das könntest du schließlich auch lassen um z.B. noch andere Methoden zu der Klasse hinzuzufügen. Dann wäre allerdings auch die PersistIntAdaptArtikel eine abstrakte Klasse.
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  7. #7
    Jens Hibbeler Jens Hibbeler ist offline Mitglied Bronze
    Registriert seit
    Oct 2005
    Beiträge
    32
    Hallo,


    ..ok. Ich denke ich hab soweit alles verstanden. Super Hilfe! Danke nochmal!

    Viele Grüße,

    Jens
     

Ähnliche Themen

  1. konkrete Klassen - abstrakte Klassen
    Von Miasto71 im Forum Java
    Antworten: 1
    Letzter Beitrag: 28.03.10, 00:18
  2. abstrakte Klassen
    Von Pherseus im Forum PHP
    Antworten: 1
    Letzter Beitrag: 27.08.06, 18:32
  3. Antworten: 5
    Letzter Beitrag: 27.07.06, 00:23
  4. Antworten: 2
    Letzter Beitrag: 05.07.06, 14:55
  5. Abstrakte virtuelle Funktionen überladen ?
    Von MetallDragon im Forum C/C++
    Antworten: 5
    Letzter Beitrag: 16.02.05, 16:53