Diamant Problem - Virtuelle Ableitung

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
insanity
Beiträge: 5
Registriert: Fr Jul 25, 2014 11:40 am
Wohnort: Kostanz

Diamant Problem - Virtuelle Ableitung

Beitrag von insanity » Sa Aug 02, 2014 12:26 pm

Hallo,

ich wurschtle mich gerade durch das Tutorial zum Diamant Problem und dem Lösungsansatz Virtuelle Ableitung. http://www.proggen.org/doku.php?id=cpp: ... ce:virtual Jetzt habe ich das Problem das ich sämtlichen Code aus dem Tutorial habe, zum Schluss jetzt sogar einfach Copy & Paste, um sicher zu gehen das ich nicht irgendwas ganz dumm übersehe, aber trotzdem bekomme ich immer die selbe Fehlermeldung meines Compilers.
Constructor for 'BluRayFullHDTelevision' must explicitly initialize the base class 'PowerConsumer' which does not have a default constructor
Hier mal mein kompletter Code, ist einfach der aus dem Tutorial. Bin da ein wenig Ratlos und weiss nicht ganz was ich tun muss, um das ganze ans laufen zu bekommen?

Code: Alles auswählen

#include <iostream>

class Display
{
public:
    int ResolutionX;
    int ResolutionY;
    
    double GetMegaPixel()
    {
        return double(ResolutionX * ResolutionY) / 1000000.0;
    }
    
    Display( int x, int y )
    : ResolutionX( x )
    , ResolutionY( y )
    {}
};

class PowerConsumer
{
public:
    int MinimalWatts;
    int MaximalWatts;
    
    inline int GetAverageConsumption()
    {
        return (MinimalWatts + MaximalWatts) / 2;
    }
    
    PowerConsumer( int min, int max )
    : MinimalWatts( min )
    , MaximalWatts( max )
    {}
};

class FullHDTelevision
: public Display
, virtual public PowerConsumer
{
public:
    FullHDTelevision( int minWatts, int maxWatts )
    : Display( 1920, 1080 )
    , PowerConsumer( minWatts, maxWatts )
    {}
};

class BluRayPlayer : virtual public PowerConsumer
{
private:
    bool DiscTrayOpen;
    
public:
    BluRayPlayer()
    : PowerConsumer( 1, 35 )
    {
        DiscTrayOpen = false;
    }
};

class BluRayFullHDTelevision
: public FullHDTelevision
, public BluRayPlayer
{
public:
    BluRayFullHDTelevision()
    : FullHDTelevision( 3, 250 )
    {
    }
};

int main(int argc, const char * argv[])
{
    
    
    return 0;
}

Nemo
Beiträge: 37
Registriert: Sa Mär 02, 2013 3:18 pm

Re: Diamant Problem - Virtuelle Ableitung

Beitrag von Nemo » Sa Aug 02, 2014 1:23 pm

Hi,

das Problem lässt sich ziemlich leicht lösen, du musst einfach einen dafault-Konstruktor für PowerConsumer definieren:

Code: Alles auswählen

class PowerConsumer
{
public:
    int MinimalWatts;
    int MaximalWatts;
   
    inline int GetAverageConsumption()
    {
        return (MinimalWatts + MaximalWatts) / 2;
    }
   
    PowerConsumer( int min, int max )
    : MinimalWatts( min )
    , MaximalWatts( max )
    {}
    
    PowerConsumer()
    {}
};
Ich verstehe nur nicht ganz, wo der default-Konstruktor gebraucht wird. :?:

insanity
Beiträge: 5
Registriert: Fr Jul 25, 2014 11:40 am
Wohnort: Kostanz

Re: Diamant Problem - Virtuelle Ableitung

Beitrag von insanity » Sa Aug 02, 2014 1:45 pm

Danke, damit funktioniert es in der Tat. :) Falls dir noch was dazu einfällt oder jemand anderes erklären kann, warum der Default Konstruktor gebraucht wird, bitte immer her damit. :)

In meinen Augen, wird der doch nie aufgerufen, oder doch?

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Diamant Problem - Virtuelle Ableitung

Beitrag von nufan » Sa Aug 02, 2014 1:46 pm

PowerConsumer hat nur einen Konstruktor, der 2 ints übergeben bekommt:

Code: Alles auswählen

PowerConsumer( int min, int max )
Das heißt du kannst Objekte nur über diesen Konstruktor erstellen.

Bei virtuellen Ableitung wird er Konstruktor der virtuellen Basisklasse immer von der am tiefsten abgeleiteten Klasse aufgerufen. Das heißt dein PowerConsumer-Konstruktor muss für den Fall BluRayFullHDTelevision auch in BluRayFullHDTelevision aufgerufen werden. Da PowerConsumer aber keinen Default-Konstruktor hat, musst du dem oben genannten Konstruktor explizit mit den geforderten int-Parametern aufrufen.

Z.B.:

Code: Alles auswählen

class BluRayFullHDTelevision
: public FullHDTelevision
, public BluRayPlayer
{
public:
BluRayFullHDTelevision()
: PowerConsumer( 3, 250 ),
  FullHDTelevision( 3, 250 )
{
}
};
Das sollte man im Tutorial korrigieren, sowie die Reihenfolge der Konstruktor-Aufrufe damit -Wall auch Genüge getan wird.

insanity
Beiträge: 5
Registriert: Fr Jul 25, 2014 11:40 am
Wohnort: Kostanz

Re: Diamant Problem - Virtuelle Ableitung

Beitrag von insanity » Sa Aug 02, 2014 1:50 pm

Ach, ok, da muss ich jetzt noch ein wenig drüber Nachdenken, um es zu verstehen, aber danke für Input. :D

EDIT:
Ahh, Ok, jetzt wird einiges klar. Ich habe meinen Code jetzt soweit geändert:

Code: Alles auswählen

class FullHDTelevision
: public Display
, virtual public PowerConsumer
{
public:
    FullHDTelevision() : Display(1920, 1080) {} // Neu dabei, um den Aufruf von PowerConsumer zu sparen, der nicht benötigt wird bei BluRayFullHDTelevision?
    FullHDTelevision( int minWatts, int maxWatts )
    : Display( 1920, 1080 )
    , PowerConsumer( minWatts, maxWatts )
    {}
};

/* … */

class BluRayFullHDTelevision
: public FullHDTelevision
, public BluRayPlayer
{
public:
    BluRayFullHDTelevision()
    : PowerConsumer(3, 250)
    // , FullHDTelevision(3, 250) Fällt weg, da doppelt?
    {
    }
};
Korrekt? Jedenfalls wenn ich jetzt ein Objekt erstelle, vom Typ BlueRayFullHDTelevision, kann ich sowohl GetMegaPixel(), als auch GetAverageConsumption(), aufrufen und bekomme die erwarteten Ergebnisse. :)

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Diamant Problem - Virtuelle Ableitung

Beitrag von Xin » Sa Aug 02, 2014 8:48 pm

Nemo hat geschrieben:Hi,

das Problem lässt sich ziemlich leicht lösen, du musst einfach einen dafault-Konstruktor für PowerConsumer definieren:
Hallo Nemo, Du löst damit das Problem, den Code kompilierfähig zu bekommen, aber Du baust ein zusätzliches Problem ein: PowerConsumer verlangt grundsätzlich klare Angaben. Wenn die diese Vorgabe lockerst, dann lockerst Du die für alle Klassen, die PowerConsumer nutzen.
Richtig wäre also die Klasse BluRayFullHDTelevision so anzupassen, dass sie die Vorgaben erfüllt.
Nemo hat geschrieben:Ich verstehe nur nicht ganz, wo der default-Konstruktor gebraucht wird. :?:
Von 'BluRayFullHDTelevision'
dani93 hat geschrieben:Das sollte man im Tutorial korrigieren, sowie die Reihenfolge der Konstruktor-Aufrufe damit -Wall auch Genüge getan wird.
Ich habe das erstmal vereinfacht geändert und mir gesondert notiert, dass ich da besser drauf eingehe.
insane hat geschrieben:Ahh, Ok, jetzt wird einiges klar. Ich habe meinen Code jetzt soweit geändert:
Optimal wäre, FullHDTelevision so zu ändern, dass Du die Watt-Zahlen nicht übergeben musst (das muss ich im Tutorial ändern), ohne die Vorgaben für den Anwender der Klasse zu verringern:

Code: Alles auswählen

class BluRayFullHDTelevision;

class FullHDTelevision
: public Display
, virtual public PowerConsumer
{
    friend class BluRayFullHDTelevision;
private:
    FullHDTelevision() : Display(1920, 1080) {} // Neu dabei, um den Aufruf von PowerConsumer zu sparen, der nicht benötigt wird bei BluRayFullHDTelevision?
public:
    FullHDTelevision( int minWatts, int maxWatts )
    : Display( 1920, 1080 )
    , PowerConsumer( minWatts, maxWatts )
    {}
};
Friends-Klassen dürften auf private Methoden zugreifen - der Rest nicht.
Das habe ich im Tutorial aber noch nicht erklärt. Das muss ich entsprechend überarbeiten.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten