Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Nach dem Standard: korrektes Interface

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
04.04.2004, 14:45 Uhr
(un)wissender
Niveauwart


Wie sieht in C++ ein Interface aus?
Muss ich einen virtuellen Destuktor angeben?
Oder noch was?

Wäre das hier korrekt?

C++:
class Observer
{
public:
    virtual void update(const Observable * observable) = 0;    
};


--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
05.04.2004, 09:57 Uhr
RHBaum



nen virtuellen Destruktor brauchst du nur .... um eben den destruktor der Basisklasse beim zersteoren auch aufzurufen.

Deine Schnittstelle hat aber keine Members die deinitialisiert werden muessen.
Zumindest von seiten von M$ ist es so praktische herangehenswisse. M$ geht sogar noch nen schritt weiter, und sagt die meistes Interfaces haben eh nur public Methoden (oder ueberwiegend) also nehm ich statt class dann eben struct :-)


C++:
struct IObserver
{
    virtual HRESULT update(const Observable * observable) = 0;    
};



Waere die M$ Variante, und funzt einigermassen zuverlaessig bei denen :p
Reine Schnittstellen haben bei mir definitiv auch keinen CTOR/DTOR ... Zumindest bist du schon mal nicht allein ! :p

Ciao ...

Dieser Post wurde am 05.04.2004 um 10:04 Uhr von RHBaum editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
05.04.2004, 12:17 Uhr
(un)wissender
Niveauwart


Richtig!
Aber, da alle Klassen mindesten 1 Byte groß sein müssen (sonst kann es vorkommen, dass zwei Objekte die gleiche Adresse haben), fällt das mit dem nicht vorhandenen Membern weg.
Wenn der Compiler nun schlauerweise erkennt, dass er auch diese 1 Byte nicht braucht, weil er nur zusehen muss, dass die Signatur stimmt (-> keine Instanz, da abstakt), so kann man den Destruktor (und alles andere) tatsächtlich weglassen.
Hm, virtual?


Bearbeitung:

Für eine konkrete Klasse ohne Member braucht man darum auch einen Destruktor!
Auch ein Byte will aufgeräumt werden!


--
Wer früher stirbt ist länger tot.

Dieser Post wurde am 05.04.2004 um 12:20 Uhr von (un)wissender editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
05.04.2004, 12:40 Uhr
RHBaum




Zitat:

Für eine konkrete Klasse ohne Member braucht man darum auch einen Destruktor!
Auch ein Byte will aufgeräumt werden


fuer "statische" Member brauchst aber auch keinen destruktor ???
Wenn keinen definierst, wird auch keiner automatisch angelegt oder ? Weil der wuerde ja soweiso nix tun ???

Beispiel ....


C++:
class X
{
public:
x(){}
~x(){ throw xxx ; }; // mal nen Fehler im Dtor werfen.
private:
int i;
};



wenn nun deine klasse erzeugst .... und wieder zerstoerst ... den fehler beim zerstoeren abfaengst ... und weitermachst, wuerde dann nen Speicherleak entstehen ? Glaub nich, weil dein Statischer member nicht durch den Destruktor zerstort wird ....

Also Destruktor brauchst um deine dynamischen variablen aufzuraeumen (sprich also zeiger mit allociertem Speicher) und definierte Logic da reinzupacken. Aber nicht um statische Members zu zerstoeren.

die Int-Variable wird vom Freestore oder Stack geraeumt, egal ob du nen destruktor hast oder ned ... wenn die Instanz geloescht(durch delete oder verlassen des Scope) wird !

Ciao ...

Dieser Post wurde am 05.04.2004 um 12:45 Uhr von RHBaum editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
05.04.2004, 12:44 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat:
RHBaum postete
nen virtuellen Destruktor brauchst du nur .... um eben den destruktor der Basisklasse beim zersteoren auch aufzurufen.

Deine Schnittstelle hat aber keine Members die deinitialisiert werden muessen.


Mag ja sein, aber wenn man eine Interface klasse hat und davon ableitet, dann wird man diese ja in der Regel so anwenden:

C++:
class InterfaceClass
{
...
};

class InterfaceImplementation: public InterfaceClass
{
...
};

...
void f()
{
     InterfaceClass p = new InterfaceImplementation(...);
     ...
     delete p;
}


Ohne virtuellen Constructor in InterfaceClass bekommt man ein fettes Speicherloch (wenn in InterfaceImplementation was freizugeben ist).

Generell gibt es in C++ ja nich das Interface-Concept wie in Java: In C++ sind Interfaces einfach Klassen, von denen man ableiten muß, um das INterface zu implementieren.
In C++ sollte man Klassen, die nicht final sind, stets mit einem virtuellen dtor versehen. Dh im Beispiel sollte ine virtueller Destrucktur her.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
05.04.2004, 12:58 Uhr
RHBaum



@virtual
ah, ok , verstehe schon ....

was passiert wenn:

C++:
struct IObserver
{
    virtual HRESULT update(const Observable * observable) = 0;    
};

class MyObserver : public IObserver
{
public:
    MyObserver( char * test = new char [1000]);
    virtual ~MyObserver( delete test; );
    virtual HRESULT update(const Observable * observable)
    {
         return S_OK;
    };    
};

void func()
{
    IObserver * pTest = new MyObserver;
    delete pTest ;
}


Ich denk in dem Fall wird der Destruktor der Hirachie generell virtual.
also hier wird der Destruktor unter VC 6.0 korrect aufgerufen ...
glaub das kann man nur unterbinden wenn das Interface nen explizit nichtvirtuellen destruktor bekommt.

Ist das Standard ?

Ciao ...


Bearbeitung von typecast:
cpp-Tags gesetzt. Macht die ganze Sache übersichtlicher :-)


Bearbeitung von RHBaum:
Ich war noch gar nicht fertig ! :p Sorry

Dieser Post wurde am 05.04.2004 um 13:08 Uhr von RHBaum editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
05.04.2004, 13:28 Uhr
(un)wissender
Niveauwart


Und noch mehr Fragen:
Muss in dem "Interface" der Zuweisungsoperator und der CopyKonstruktor überschrieben werden?
Sollten die Konstruktoren etc. vielleicht protected sein?
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
05.04.2004, 13:44 Uhr
RHBaum



@(un)wissender
von virtual:

Zitat:

Generell gibt es in C++ ja nich das Interface-Concept wie in Java:
In C++ sollte man Klassen, die nicht final sind, stets mit einem virtuellen dtor versehen.



deswegen wird dir der "Standard" da sicher nicht so richtig weiterhelfen.
Die einzigen Anwendungen die ich kenne, die in C++ das "Konzept" der Interfaces extensiv nutzen und auch denken dass sie die Urheber sind, ist M$ mit der ATL.
und die trennen strikt zwischen Deklaration von Schnittstellen (Interfaces) und Implementation.
Das heisst bei denen sind die Interfaces wirklich nur die deklaration der User-Funktionen. Fuer das Verhalten ist die Implementation zustaendig. Sprich die interfaces haben keinen Destruktor, dafuer ist die erste Ableitung zustaendig, die Funktionalitaet implementiert.
Beispiel IUnknown -> IDispatch -> IDispatchImpl
Erst IDispatchImpl hat den virtuellen Destruktor.
Copy Konstruktoren und ZuweisungsOps wirst da nicht finden, da sie nen eigenes System von HandHabung der Schittstellen unterstuetzen (IDispatch und QueryInterface) .... welches auch Aggregation und multiple schnittsellen beruecksichtigt ..... Aber das ist M$ Zeugs :p

Ich denk mal auch, das die logsichen Probleme grade von Schnittstellen in bezug auf CopyConstruktoren und Zuweisungsops der Grund fuer die eher zaghafte Verbreitung "reiner" Schnittstellen sind:

Stell dir vor du hast ne Hirachie :
IAbtstr1 <- IAbtstr2 <- IAbtstr3 <- Concret1 <- Concret2 <- Concret3;

IAbtstr1 * pGeneralPointer1 = new Concret1;
IAbtstr1 * pGeneralPointer2 = new Concret3(pGeneralPointer1 );

versuch mal deinem system hier beizubringen, welchen CCtor usw es zu verwenden hat ....
In C++ fehlt deinem generellen Zeiger die Information, welche klasse genau dahinter steht .... Koennte man ueber RTI loesen ... aber die Nachteilen sind ja bekannt ....

Ciao ...

Dieser Post wurde am 05.04.2004 um 13:57 Uhr von RHBaum editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
05.04.2004, 15:43 Uhr
(un)wissender
Niveauwart


@RHBaum
Es ist bei deinem Beispiel meiner Meinung nach völlig klar, welche Konstruktoren verwendet werden sollen, meinem Compiler wohl auch.

Mein genereller Zeiger hat die Informationen, die er braucht durch die vtable!
Das er nicht weiß (ohne RTTI), ob er nun auf Concret1 oder Concret3 zeigt, ist ja auch beabsichtigt(->minimale Abhängigkeiten) und in Java genauso!
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: