Probleme bei rein virtuellem Operator



  • Hey Leute,

    folgendes Problem: Hab eine Hierarchie mit drei Stufen.
    Den beiden oberen, abstrakten habe ich, eben damit sie abstrakt sind, den rein virtuellen Operator==

    bool operator ==(const Abstrakte_Klasse&) = 0;
    

    als Methode mitgegeben.

    In der dritten Stufe, in der ich den Operator überlade

    bool operator ==(const Konkrete_Klasse&);
    

    (und auch definiert habe), gibt es aber Probleme.

    Wenn ich nämlich die konkrete Klasse instantiieren will, erhalte ich diese

    error C2259: 'TVPrivat' : cannot instantiate abstract class due to following members:
    

    und diese

    warning C4259: 'bool __thiscall Massenmedien::operator ==(const class Massenmedien &)' : pure virtual function was not defined
    

    Fehlermeldung. Und dieses Warning gibt er für alle Basisklassen der konkreten Klasse an, was mich ein wenig verwirrt. Ist es denn nicht der Sinn einer rein virtuellen Funktion, nicht definiert zu werden? 😕

    Wäre echt nett, wenn mir C++-Anfänger(ca.3/4 Jahr) mal jemand helfen könnte.



  • Sind ja auch verschiedene Funktionen ;), d.h. bei dir wird die Funktion == einfach überladen (mit anderer Parameterliste) und keine Implementierung für die eigentliche rein virtuelle Funktion geliefert.
    In der abgeleiteten Klasse müsstest du imho auch

    virtual bool operator ==(const Abstrakte_Klasse&);
    

    nehmen. Auf die Schnelle fällt mit da auch nur ein, dass du dann in dem Operator nach Konkrete_Klasse dynamic_cast'est. Aber weiß net ob des ne so tolle Lösung ist.



  • probiers mal mit

    virtual bool equals(Abstrakte_Klasse& b)=0;
    

    und vielen geerbten und redefinierten equals.
    und nur einmal global

    bool operator==(Abstrakte_Klasse& a,Abstrakte_Klasse& b){
       return a.equals(b);
    }
    


  • Danke für die Tipps, ich werd das heute mal ausprobieren und mir wohl eine neue Funktion einfallen lassen müssen, um die abstrakten Klassen abstrakt zu halten.



  • Wenn dir gar keine andere Methode einfällt, die du abstrakt setzen kannst - nimm den Destruktor:

    class base
    {
    public:
      ...
      virtual ~base() = 0;
      ...
    };
    
    base::~base() {} //das hier ist notwendig, sonst können abgeleitete Klassen nicht zerstört werden
    


  • Cool, wusste gar nicht, dass das geht. Danke!



  • Sorry für den Doppelpost, aber...
    @Volkard: Die Idee ist gut, aber wie könnte ich sowas verhindern?

    Konkrete_Klasse1 a;
    Konkrete_Klasse2 b;  // Auch von Abstrakte_Klasse abgeleitet!
    
    cout << a == b;
    

    Da Konkrete_Klasse1 und Konkrete_Klasse2 nicht die selben Attribute haben, geht das wohl kaum gut aus.
    Irgendwelche Vorschläge?
    [Edit] Geht ganz sicher ganz gut aus. Der Compiler kritisiert jetzt an jeder konkreten equals-Funktion, dass Abstrakte_Klasse dieses oder jenes Attribut nicht habe - Hilfe!

    Aja, nochwas: Wie kann man

    funktion_xy(void) const;
    

    mit einer rein virtuellen Funktion machen, so?

    virtual funktion_xy(void) const = 0;
    

    Sieht irgendwie seltsam aus, würde ich meinen.



  • Zweiundvierzig schrieb:

    Aja, nochwas: Wie kann man

    funktion_xy(void) const;
    

    mit einer rein virtuellen Funktion machen, so?

    virtual funktion_xy(void) const = 0;
    

    Sieht irgendwie seltsam aus, würde ich meinen.

    jo stimm so. Die konrete Implementation dann mit

    virtual funktion_xy(void) const;
    

    in der konkretenKlasse.



  • Zweiundvierzig schrieb:

    Da Konkrete_Klasse1 und Konkrete_Klasse2 nicht die selben Attribute haben, geht das wohl kaum gut aus.
    Irgendwelche Vorschläge?

    dynamic_cast ist jetzt dein freund.



  • volkard schrieb:

    Zweiundvierzig schrieb:

    Da Konkrete_Klasse1 und Konkrete_Klasse2 nicht die selben Attribute haben, geht das wohl kaum gut aus.
    Irgendwelche Vorschläge?

    dynamic_cast ist jetzt dein freund.

    Dann kann man doch auch gleich meine Lösung nehmen, oder net?



  • Mit dynamic_cast kann ich einfach diese Klasse entsprechend casten, ohne dass irgendwelche Nachteile entstehen? Oder muss ich auf irgendetwas achten?



  • Wenn die Klasse nicht gecastet werden kann wird ne Exception std::bad_cast geschmissenm, d.h. wenn bad_cast geschmissen wird, dann kann auch net verglichen werden.



  • Zweiundvierzig schrieb:

    Konkrete_Klasse1 a;
    Konkrete_Klasse2 b;  // Auch von Abstrakte_Klasse abgeleitet!
    
    cout << a == b;
    

    Da Konkrete_Klasse1 und Konkrete_Klasse2 nicht die selben Attribute haben, geht das wohl kaum gut aus.
    Irgendwelche Vorschläge?
    [Edit] Geht ganz sicher ganz gut aus. Der Compiler kritisiert jetzt an jeder konkreten equals-Funktion, dass Abstrakte_Klasse dieses oder jenes Attribut nicht habe - Hilfe!

    Um beide Klassen zu vergleichen, solltest Du das mit Attributen machen, die beiden gemeinsam sind, d.h., Du solltest den operator== in einer gemeinsamen Basisklasse definieren (nicht nur deklarieren).



  • Ok, ich habe gerade gesehen, dass man einen Pointer dafür braucht. Tut's eine Referenz auch? Und kann man einen dynamic_cast auf ein constant-Objekt anwenden?

    @tim_g: Das ist mir schon klar, aber ich will ja auch spezifische Attribute vergleichen können, die eben von Unterklasse zu Unterklasse verschieden sind.



  • Zweiundvierzig schrieb:

    Ok, ich habe gerade gesehen, dass man einen Pointer dafür braucht. Tut's eine Referenz auch?

    naa, nix gut referenz. die kann nicht so einfach 0 werden, um anzuzeigen, daß das casten nicht klapt.

    ich dachte an

    bool operator==(Abstrakte_Klasse& a,Abstrakte_Klasse& b){ 
       return a.equals(b); 
    }
    

    nebst

    bool Kinkrete_Klasse1::equals(Abstrakte_Klasse& b){
       Kinkrete_Klasse1* pkk1=dynamic_cast<Kinkrete_Klasse1*>(&b);
       if(pkk1==0) return false;
       und ab hier die members von this und pkk1 vergleichen. 
    }
    

    aber es sind viele lösungen denkbar mit vielen vorteilen und nachteilen. und das da sieht für mich nicht toll aus. könnte aber klappen.



  • volkard schrieb:

    Zweiundvierzig schrieb:

    Ok, ich habe gerade gesehen, dass man einen Pointer dafür braucht. Tut's eine Referenz auch?

    naa, nix gut referenz. die kann nicht so einfach 0 werden, um anzuzeigen, daß das casten nicht klapt.

    ehm... volkard 🙂 Bei Referenzen fliegt ne bad_cast exception 😉 , um anzuzeigen, dass der Cast net geht.
    *duck und vor volkards antwort davonrenn*



  • bluecode schrieb:

    ehm... volkard 🙂 Bei Referenzen fliegt ne bad_cast exception 😉 , um anzuzeigen, dass der Cast net geht.
    *duck und vor volkards antwort davonrenn*

    du hast http://www.c-plusplus.net/forum/viewtopic-var-t-is-144356-and-postdays-is-0-and-postorder-is-asc-and-start-is-0.html gelesen, gell?



  • Okay, danke für díe Hilfe. Ab jetzt komm ich alleíne klar. 🙂


Log in to reply