JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=65f2a322c795eed2aeeb44ea78720aadMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Vererbung für Fortgeschrittene

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
AFE-GmdG
JLI MVP
JLI MVP


Alter: 44
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 19.12.2005, 15:40    Titel: Vererbung für Fortgeschrittene Antworten mit Zitat

Ich weiss nicht genau, ob nur mir das passiert - oder ob meine Ansprüche einfach nur viel zu hochgesteckt sind... Aber ich habe mir geschworen, wenn ich was mache, dann richtig.

Problembeschreibung:
Für eine DLL, welche mehrere Klassen exportieren soll(te), welche untereinander abgeleitet sind möchte ich jetzt vernünftige Interfaces definieren. Sprich ich habe diese DLL schon mal fertig programmiert - war mit dem Ergebnis aber nicht 100%ig zu frieden. Der Vorteil von Interfaces ist einfach: man hat saubere, voneinander getrennte Schnittstellen nach außen und der Anwender der DLL sieht keine unnötigen privaten oder geschützten Methoden. Das räumt nebenbei auch Intellisense auf.

Präzisierung:
Einfach nur mal Interfaces definieren ist ja nicht, also habe ich den alten Code erstmal zur Seite gelegt und angefangen, die Klassen neu zu implementieren - und diesmal gleich richtig und sauber. Ich kann vieles zwar mit Copy und Past übernehmen (so unsauber hab ich die DLL schliesslich auch nicht programmiert) aber anderes mach ich grundsätzlich neu. Nun habe ich allerdings ein Verständnisproblem mit abgeleiteten Interfaces und davon erbenden, ebenfalls abgeleiteten Klassen.

CPP:
// Interfaces.h - definiert alle Interfaces.
#pragma once

#include <Windows.h>

__interface Interface 1
{
  int Funktion1(const int) const;
};

__interface Interface2 : public Interface1
{
  int Funktion2(const int) const;
};
Interface1 definiert Funktion1 und Interface2 definiert Funktion2 und erbt zusätzlich Funktion1 von Interface1.

CPP:
// Klasse1.h / Klasse1.cpp (Zur Vereinfachung ist das Beispiel hier inline)
#include "Interfaces.h"

class Klasse1 : public Interface1
{
public:
  int Funktion1(const int Wert) const
  {
    return Wert+1;
  }

};
Mit Klasse1 ist alles in Ordnung, sie lässt sich ohne probleme übersetzen.

CPP:
// Klasse2.h / Klasse2.cpp (Zur Vereinfachung ist das Beispiel hier inline)
#include "Interfaces.h"
#include "Klasse1.h"

class Klasse2 : public Klasse1, public Interface2
{
public:
  int Funktion2(const int Wert) const
  {
    return Wert-1;
  }

};
Klasse2 lässt sich zwar (so) übersetzen, ist aber abstrakt, weil von Interface1 Funktion1 nicht definiert ist - was ich persönlich nicht verstehe, da ich ja explizit von Klasse1 erbe, welche Interface1 und damit Funktion1 implementiert.
Ich kann jetzt zwar Funktion1 in Klasse2 ebenfalls implementieren nur geht das mir persönlich gegen den Strich, da ich somit doppenten Code erzeuge, der wieder doppelt gewartet werden muss. Funktioniert Vererbung nicht so, wie ich es mir hier vortstelle oder habe ich einen [Denk]Fehler im Ansatz?

Hoffe auf Hilfe,
AFE-GmdG
_________________
CPP:
float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Christian Rousselle
Site Admin


Alter: 47
Anmeldedatum: 19.07.2002
Beiträge: 1630

Medaillen: Keine

BeitragVerfasst am: 19.12.2005, 16:07    Titel: Antworten mit Zitat

Wenn ich das richtig sehe (wobei ich nicht sehe, wo man so ein Konstruktion benötigt), erbt Klasse2 Funktion1 von Klasse1 (dort ist sie implementiert) und nochmal von Interface2 (via Interface1) - dort ist sie nicht implementiert, deshalb der Fehler. Ich glaube nicht, dass der Compiler verstehen kann, dass du hier die gleiche Funktion meinst...
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
GreveN
JLI Master


Alter: 37
Anmeldedatum: 08.01.2004
Beiträge: 901
Wohnort: Sachsen - Dresden
Medaillen: Keine

BeitragVerfasst am: 19.12.2005, 16:25    Titel: Antworten mit Zitat

Hm... vlt. könnte dir eine virtuelle Ableitung weiterhelfen.
Also wenn einer abgeleiteten Klasse 2 Basisklassen zugrunde liegen, denen wiederrum eine gemeinsame Basisklasse zugrunde liegt, so teilen sich bei einer virtuellen Ableitung beide Klassen quasi dieselbe 'Instanz' (weiß nicht, ob man in diesem Falle davon sprechen kann, ich hoffe es ist dennoch klar, was ich meine) der untersten Basisklasse.
In deinem konkreten Falle, könnte dir das dahingehend helfen, dass die Methode nur noch einmal vorhanden wäre.

Weiß nicht, ob das irgendwie helfen kann/könnte, habe das selber noch nie ausprobiert, nur mal vor geraumer Zeit den Stroustrup gelesen, welcher nebenbei in dieser Hinsicht auch einiges zu bieten hat, vlt. lohnt sich ja ein Blick.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Yahoo Messenger MSN Messenger
AFE-GmdG
JLI MVP
JLI MVP


Alter: 44
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 19.12.2005, 16:29    Titel: Antworten mit Zitat

Christian Rousselle hat Folgendes geschrieben:
(wobei ich nicht sehe, wo man so ein Konstruktion benötigt)

Ganz einfach: Klasse2 ist eine Klasse1 (und mehr).
Ich habe als Anwender der DLL aber keinen Zugriff auf auf die Klassen sondern nur auf die Interfaces.
Es gibt eine Funktion, mit der ich einen Instanz von Klasse2 bekommen kann (als Interfacepointer). Und Interface2 ist eben auch ein Interface1:
CPP:
Interface1* Foo=FunktionWelcheInterface2PointerZurückgibt();

Ich möchte die Vererbungshirarchie der Klassen in den Interfaces mit abbilden.

@GreveN
Interface bedeutet ja, dass der Compiler virtuelle Funktionen generiert.
also eigendlich steht statt
CPP:
int Funktion1(const int) const

folgendes in den Objektdateien
CPP:
virtual int Funktion1(const int) const=0

(gleiches gilt natürlich für Funktion2)
_________________
CPP:
float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Patrick
Dark JLI Master



Anmeldedatum: 25.10.2004
Beiträge: 1895
Wohnort: Düren
Medaillen: Keine

BeitragVerfasst am: 19.12.2005, 16:49    Titel: Antworten mit Zitat

Mit dem =0; wäre ich mir da nicht so ganz sicher. Muss ich nochmal nachschlagen. ich glaub mit =0; war das nämlich nicht.
_________________
'Wer der Beste sein will muss nach Perfektion streben und jede Gelegenheit nutzen sich zu verbessern.' - KIA
[ German Game Dev | Boardsuche hilft sehr oft | Google rockt | Wie man Fragen richtig stellt | ICQ#: 143040199 ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Christian Rousselle
Site Admin


Alter: 47
Anmeldedatum: 19.07.2002
Beiträge: 1630

Medaillen: Keine

BeitragVerfasst am: 19.12.2005, 21:25    Titel: Antworten mit Zitat

Also mal genauer:

Code:

__interface If1
{
   void f1();
}

sorgt dafür, dass folgende Klassendefinition verwendet wird:

Code:

class If1
{
   public:
     virtual void f1() = 0;
};


D.h. alle Funktionen des Interace werden automaitsch abstrakt/virtuell.

Was ich sagen wollte ist, dass du durch deine Deklaration zwei mal die Funktion Funktion1 im deiner Hierarchie hast. Achtung! Hierbei handelt es sich um zwei verschiedene Funktionen, die zufällig den gleichen Namen haben. Du implementierst sie zwar einmal dadurch, dass du sie in Klasse1 angibst, sie kommt aber ein weiteres mal durch die Vererbung von Interface2 rein (es handelt sich aber um eine andere Funktion). Da sie auf diesem Weg nicht implementiert wird, fehlt dir in deiner Hierarchie die Definition von int Interface1::Funktion1(const int) const in Klasse2. Das ist meiner Meinung nach logisch.

GreveN meint was anderes:

Es gibt virtuell Basisklassen, die man für dein Problem verwenden könnte, obwohl ich das Problem hier eher im Design sehe - verwendet besser eine Proxyklasse, die die Funktionen die du öffentlich machen willst nach außen gibt.

Mit virtuellen Basisklassen kannst du es folgendermaßen lösen.

CPP:
class Interface1
{
   public:

      virtual int Funktion1(const int) const = 0;
};

class Interface2 : public virtual Interface1
{
   public:
      
      virtual int Funktion2(const int) const = 0;
};

class Klasse1 : public virtual Interface1
{
   public:
 
      int Funktion1(const int Wert) const
      {
         return Wert+1;
      }
};

class Klasse2 : public virtual Klasse1, public Interface2
{
   public:

      int Funktion2(const int Wert) const
      {
         return Wert-1;
      }
};


Es gibt dabei aber eine Warnung.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum