high sophisticated Compile Fehler .. verschwindet



  • SeppJ schrieb:

    virtual ~Base() =0 {}
    

    Das würde mich jetzt auch wundern, wenn's da keine Mecker gäbe. Was soll das denn bitte sein? =0 und Funktiondefinition durch {} schließen sich gegenseitig aus.

    Ja - ausgenommen beim Destruktor. Den Tipp habe ich aus einem der Scott Meyers Bücher. Man spart sich halt den Body des Destruktors und erzwingt eine abstrakte Basisklasse
    .. aber das ist hier nicht das Thema. Wäre nett, wenn sich noch mal jemand meiner ursprünglichen Frage zuwenden würde. Ich bin noch nicht ganz überzeugt.

    Gruß
    Werner



  • Und warum sagt g++: test.cpp:6: Fehler: pure-specifier on function-definition? Desweiteren ist der Fehler "inline" mit g++ nicht reproduzierbar. Was willst du mehr?


  • Mod

    Werner Salomon schrieb:

    Ja - ausgenommen beim Destruktor.

    Der Standard sagt etwas anderes.

    Werner Salomon schrieb:

    Den Tipp habe ich aus einem der Scott Meyers Bücher.

    Jedenfalls nicht in den Effective-Büchern.

    Die zu Pups gehörende Überladung wird, wenn sie außerhalb von Pups defeiniert wird, per unqualifziertem Lookup gefunden. Da es hier zu einem Substitutionsfehler kommt, muss diese Überladung aber verworfen werden. Selbst ohne SFINAE wäre es jedenfalls eine schlechtere Überladung als die zu base gehörende (Standartkonvertierung vs. Konvertierung mittels Konstruktor beim 2. Parameter). Da die fehlerhafte Destruktordeklaration bereits gemeldet wird, steht es dem Compiler frei, danach noch jede Menge Unfug zu melden (das könnte hier z.B. daran liegen, dass die Base-Definition eben wegen der Fehlerhaften Destruktordeklaration unvollständig bleibt und der Compiler beim weiteren Parsen unsicher ist, ob denn nun ein Copykonstruktor möglich ist oder nicht. Jedenfalls sind alle gemeldeten Folgefehler ohne große Relevanz.

    Wird der zu Pups gehörende Operator inline in Pups definiert, wird er in dem Ausdruck

    cout << *ptr_Base
    

    gar nicht erst gefunden werden (weil eine friend-Deklaration den entsprechenden Namen nicht in den umligenden Namensraum injiziert und ADNL die Klasse Pups gar nicht erst betrachtet), folglich wird auch keine Fehlermeldung produziert werden.



  • Werner Salomon schrieb:

    Bzw. wodurch unterscheiden sich diese beiden friend-Funktionen von einander?

    Der C++-Standard sagt dazu:

    Friends §11.4/5 schrieb:

    A function can be defined in a friend declaration of a class if and only if the class is a non-local class (9.8),
    the function name is unqualified, and the function has namespace scope. [Example:

    class M {
    friend void f() { } // definition of global f, a friend of M,
    // not the definition of a member function
    };
    

    —end example] Such a function is implicitly inline. A friend function defined in a class is in the (lexical) scope of the class in which it is defined. A friend function defined outside the class is not (3.4.1).

    Unqualified name lookup §3.4.1/9 schrieb:

    Name lookup for a name used in the definition of a friend function (11.4) defined inline in the class granting friendship shall proceed as described for lookup in member function definitions. If the friend function is not defined in the class granting friendship, name lookup in the friend function definition shall proceed as described for lookup in namespace member function definitions

    Also wird ADL nicht in beiden Fällen herangezogen.

    Edit: camper war schneller und ausführlicher 😉



  • camper schrieb:

    Werner Salomon schrieb:

    Ja - ausgenommen beim Destruktor.

    Der Standard sagt etwas anderes.

    Richtig. Der Standard sagt, dass für alle pure-virtual-Funktionen eine Implementation bereitgestellt werden kann.

    camper schrieb:

    Werner Salomon schrieb:

    Den Tipp habe ich aus einem der Scott Meyers Bücher.

    Jedenfalls nicht in den Effective-Büchern.

    Effective C++, Third Edition, Item 34 (S. 166/167).



  • > Effective C++, Third Edition, Item 34 (S. 166/167).

    Nicht in der deutschen von Addison Wesley.



  • Effective C++, Item 34 schrieb:

    (...)

    Some people object to the idea of having separate functions for prividing interface and default implementation, such as fly and defaultFly above. For one thing, they note, it pollutes the class namespace with a proliferation of closely related function names. Yet they still agree that interface and default implementation should be separated. How do they resolve this seeming contradiction? By taking advantage of the fact that pure virtual functions must be redeclared in concrete derived classes, but they may also have implementations of their own. Here's how the Airplane hierarchy could take advantage of the ability to define a pure virtual function:

    class Airplane {
    public:
      virtual void fly(const Airport& destination) = 0;
    
      ...
    };
    
    void Airplane::fly(const Airport& destination)
    {
      default code for flying an airplane to
      the given destination
    }
    
    class ModelA : public Airplane {
    public:
      virtual void fly(const Airport& destination)
      { Airplane::fly(destination); }
    
      ...
    };
    
    (...)
    

  • Mod

    Ad aCTa schrieb:

    > Effective C++, Third Edition, Item 34 (S. 166/167).

    Nicht in der deutschen von Addison Wesley.

    In meiner englischen Ausgabe auch nicht.


  • Mod

    seldon schrieb:

    Effective C++, Item 34 schrieb:

    (...)

    Some people object to the idea of having separate functions for prividing interface and default implementation, such as fly and defaultFly above. For one thing, they note, it pollutes the class namespace with a proliferation of closely related function names. Yet they still agree that interface and default implementation should be separated. How do they resolve this seeming contradiction? By taking advantage of the fact that pure virtual functions must be redeclared in concrete derived classes, but they may also have implementations of their own. Here's how the Airplane hierarchy could take advantage of the ability to define a pure virtual function:

    class Airplane {
    public:
      virtual void fly(const Airport& destination) = 0;
    
      ...
    };
    
    void Airplane::fly(const Airport& destination)
    {
      default code for flying an airplane to
      the given destination
    }
    
    class ModelA : public Airplane {
    public:
      virtual void fly(const Airport& destination)
      { Airplane::fly(destination); }
    
      ...
    };
    
    (...)
    

    Und? Da steht nicht, dass eine Funktion in der gleichen Deklaration, die auch die Definition enthält (d.h. eine inline-Definition in der Klassendefinition), reinvirtuell deklariert werden darf. Da steht lediglich, dass eine reinvirtuelle Funktion eine Funktionsdefinition haben darf (im Falle des Destruktors: (praktisch) muss). Diese Regeln bringt man zusammen, indem man sich überlegt, dass eine reinvirtuelle Deklaration inline-Definitionen in der Klassedefinition ausschließt.

    Und siehe da, bei Meyers erfolgt die Funktionsdefinition auch außerhalb der Klassendefinition.



  • Wenn's um die Syntax geht, geht das so hintereinander weg nicht (wenn's darum ging - mein Fehler, ich habe das so nicht wahrgenommen). Man kann pure-virtual-Funktionen (wenn man das unbedingt will) aber immer noch inline deklarieren:

    struct foo {
      inline virtual ~foo() = 0;
    };
    
    inline foo::~foo() { }
    


  • Der MSVC unterstützt diese Form (als Erweiterung), ist aber, wie schon gesagt wurde, kein Standard:

    virtual ~Base() =0 {}
    

    Ist halt bequem zu schreiben...



  • Ein Dankeschön an camper und Nexus; insbesondere für den Hinweis auf 3.4.1 Absatz 9.
    Gruß
    Werner


Anmelden zum Antworten