Mehrfachvererbung, gleiche Variable?



  • Hallo,
    ich beschäftige mich gerade mit Mehrfachvererbung und den unsing-Sachen darin.
    Soweit ist auch alles klar und meine Programmierungen tun was sie sollen, aber ein Punkt ist mir unklar.

    Ich mache es anhand einer XML-Klasse, weil man dort wahrscheinlich am Besten versteht was ich meine. Als Grundlage dient mir eine Klasse, die ich ML-Klasse nenne und mir als Grundlage für HTML, XML, RSS, etc dienen soll.

    class MLObject
    {
      virtual string Ausgabe();
    };
    
    class MLText : public MLObject
    {
      string Inhalt; // z.B. "Hallo C++ler & andere"
      virtual void VerifyInhalt();
    };
    
    class MLTag : public MLObject
    {
      string TagName;  // z.b. "hallo"
      virtual void VerifyTagName(); // Nur Zahlen und Buchstaben
      virtual string Ausgabe(); // z.B. <hallo>
      virtual void AddInhalt(MLObject* addObject); // Damit man in die Tags auch was reinlegen kann...
    };
    
    class MLTagClosed : public MLTag
    {
      virtual string Ausgabe(); // z.B. <hallo></hallo>
    };
    
    class XMLText : public MLText
    {
      virtual void VerifyInhalt(); // z.B. "Hallo C++ler &amp; andere"
    };
    
    class XMLTag : public MLTag
    {
      virtual void VerifyTagName(); // MLTag::VerifyTagName() und in Gro&szlig;buchstaben wandeln. z.B. <HALLO>
    };
    
    class XMLTagClosed : public MLClosedTag, XMLTag
    {
      using XMLTag::VerifyTagName(); // Damit in Gro&szlig;buchstaben konvertiert wird
      using MLTagClosed::Ausgabe(); // Damit auch ein Endtag gebaut ausgegeben wird. z.B. <HALLO></HALLO>
    };
    

    Soweit der Aufbau und die Vererbung. In MLText kann alles gespeichert werden, in XMLText wird der Inhalt noch mit Entities versehen. In MLTag kann der Tagname nur Klein- und Großbuchstaben beinhalten, in XMLTag wird der Tag-Name in Großbuchstaben konvertiert. Bei xxTagClosed wird bei der Ausgabe jeweils noch ein End-Tag mit ausgegeben.

    Jetzt habe ich natürlich in MLTag eine Variable definiert, die mir den Tag-Namen speichert. Diese Variable vererbt sich natürlich in MLClosedTag, XMLTag und auch in XMLTagClosed.

    Aber meine Frage ist: Da ich bei XMLTagClosed von zwei Klassen erbe, die beide eine Variable TagName haben, gibt es dort den TagName nur einmal oder zweimal? Der kommt ja über MLClosedTag und über XMLTag zweimal an. Was passiert wenn ich in XMLClosedTag die Funktion VerifyTagName aufrufe? Diese liegt in XMLTag und ist über "using XMLTag::VerifyTagName" in den Header eingebunden. Sieht diese Funktion die gleiche Variable TagName wie die Funktion "using MLClosedTag::Ausgabe"?

    Bitte bringt mir jemand Licht ins dunkel, da meine Bücher sich um das Thema leider nicht so richtig auslassen. (Bei Funktionen schon, aber bei Variablen ist das unklar.)

    Klar hab ich mal nen Debugger drüber laufen lassen und für mich sieht es so aus, als gäbe es den TagName nur einmal, aber ich würde das lieber mal von jemanden wissen, der sich besser damit auskennt als ich.

    Danke,
    Stefan



  • class XMLTagClosed : public MLClosedTag, XMLTag
    {
      using XMLTag::VerifyTagName(); // Damit in Gro&szlig;buchstaben konvertiert wird
      using MLTagClosed::Ausgabe(); // Damit auch ein Endtag gebaut ausgegeben wird. z.B. <HALLO></HALLO>
    };
    

    Ich sehe das erste Mal diese Verwendungsart von using in C++. Kann mit jemand helfen?

    Ansonsten: http://en.wikipedia.org/wiki/Diamond_problem



  • Sorry, ich hab nen Syntax-Fehler drinnen (Die Klammern beim using müssen weg):

    class XMLTagClosed : public MLClosedTag, XMLTag
    {
      using XMLTag::VerifyTagName; // Damit in Gro&szlig;buchstaben konvertiert wird
      using MLTagClosed::Ausgabe; // Damit auch ein Endtag gebaut ausgegeben wird. z.B. <HALLO></HALLO>
    };
    

    Das using sagt, welche Funktionen verwendet werden sollen, wenn zwei Funktionen mit dem gleichen Namen bei der Vererbung auftauchen.

    Hab ich aus dem Buch: Die C++ Programmiersprache von Bjarne Stroupstrup, 4. Auflage.



  • knivil schrieb:

    Ansonsten: http://en.wikipedia.org/wiki/Diamond_problem

    Wiki Diamond Problem schrieb:

    C++ by default follows each inheritance path separately, so a D object would actually contain two separate A objects, and uses of A's members have to be properly qualified. If the inheritance from A to B and the inheritance from A to C are both marked "virtual" (for example, "class B : virtual public A"), C++ takes special care to only create one A object, and uses of A's members work correctly. If virtual inheritance and nonvirtual inheritance are mixed, there is a single virtual A and a nonvirtual A for each nonvirtual inheritance path to A.

    Wenn ich das richtig verstehe wird die Grundklasse nur einmal erzeugt und folglich ist die Variable TagName auch nur einmal da. Richtig?



  • Falsch, nur wenn virtuelle Vererbung spezifiziert wurde. Aber da sollte sich mal jemand aeussern, der den Standard kennt.

    Auch solltest du vielleicht aus deinen Oberklassen reine Interfaces machen, dann hast du weniger Problem. Aus tagName wird dann eine virtuelle Funktion a la virtual const char* tagName() const oder so.



  • Ist es beabsichtigt das XMLTagClosed privat von XMLTag erbt?



  • Äh nein, es soll schon public erben. Bei Sample ist mir das durchgerutscht.


Anmelden zum Antworten