Problem bei gleichem Methodenname wie Klassenname



  • Hallöchen

    Ich bin gerade dabei C++ code geschrieben/compiliert mit MS Visual Studio 2005 auf Linux / gcc 4.2 zu portieren. Dabei bin ich auf folgendes Problem gestossen (Namen hab ich der Einfachheit halber geändert):

    In einem Header-file wird ein Interface definiert:

    namespace x
    {
    class A;
    
    class B
    {
      public:
    
        virtual A* A() = 0;
    };
    }
    

    Die Klasse A wird vorwärts deklariert damit der Rückgabewert der Methode A bekannt ist. gcc meldet folgende Fehlermeldung:
    "declaration of virtual 'x::A x::B::A()' changes meaning of 'A' from 'struct x::A'"*

    Irgendwie scheint gcc nicht zu merken, dass "A()" eine Methodendeklaration ist und nichts mit der Klasse A zu tun hat... Ich hab aber keine Ahnung wie ich den Fehler beheben kann...



  • tlrs_ing schrieb:

    Ich hab aber keine Ahnung wie ich den Fehler beheben kann...

    Ganz einfach: Indem du die Methode anders nennst. A() ist bereits der Konstruktor der Klasse A. nenn die Methode GetA() oder MakeA() - was eben angebracht ist.



  • Das hab ich vergessen zu erwähnen. Ich möchte, wenn möglich, die Methode A() nicht umbenennen. Ist mir schon klar, dass das eine Variante wär. Aber wie gesagt, das ganze ist eine Portierung und sollte so wenig verändern wie möglich.

    Zudem ist mir wie gesagt nicht ganz klar warum er die Methode A() mit dem Konstruktor der Klasse A verwechselt. Der "full qualified namespace" der Methode ist ja x::B::A() und der vom Konstruktor ist ja x::A::A(). Zudem hätt ich erwartet, dass gcc merkt, dass die betreffende Zeile eine Methodendeklaration ist und kleine Klasseninstanziierung oder sonst was...

    Aber eben, ich weiss nicht genau ob gcc ein Fehler macht oder ob's einfach nicht ANSI C entspricht oder ob man gcc sonst irgendwie auf die Sprünge helfen könnte...
    Bin für weitere Ratschläge dankbar! 😉



  • Ansi C entsprichts nicht.. wenn schon Ansi C++... 🕶



  • Vielleicht stört sich GCC nur daran dass du "A" innerhalb einer Deklaration einmal als "x::A" verwendest, und gleichzeitig "A" als "x::B::A" deklarierst.
    Ob sowas laut Standard erlaubt ist weiss ich nicht, aber ich finde es eigentlich ganz gut, dass es GCC nicht "durchgehen" lässt. Ist ja auch ziemlich ... grauslich.

    Schuss ins Blaue: versuch mal einen Typedef zu machen:

    namespace x
    {
    class A;
    
    class B
    {
    public:
    
        typedef A x_A;
    
        virtual x_A* A() = 0;
    };
    }
    


  • Hab mal versucht, das unter MSVC zu machen, der schluckts. Was natürlich bei weitem keine Garantie ist dass der Standard es erlaubt.



  • Das ist genau mein Problem 🙂

    Wie eingangs erwähnt stammt der Originalcode von Visual Studio 2005. Und dort gehts problemlos. Wobei sich Visual Studio bei weitem weniger streng an die ANSI Normen hält als der gcc.
    Aber der gcc ist ja auch nicht perfekt... 😉
    Ich werd den Ansatz mit dem typedef mal probieren. Und vielleicht würde ja ein include des Header files der Klasse A (anstatt der Vorwärtsdeklaration) helfen...

    Und ja, wenn das "mein" code wär, würde die Methode schon lange "getA()" heissen... 😉



  • Wobei sich Visual Studio bei weitem weniger streng an die ANSI Normen hält als der gcc.

    Das stelle ich mal in Frage bei den neueren MSVC Compilern.
    Simon



  • so, konnte das problem lösen.

    hab dir function mit

    virtual x::A* A() = 0;
    

    deklariert. Dann frisst gcc das... 🙂

    Welche version jetzt mehr ANSI entspricht (mit oder ohne namespace angabe) dürft ihr selber nachschauen 😉

    Ich musste einfach feststellen, dass visual studio ein paar mühsame eigenschaften hat... z.b. kompiliert der auch wenn man die standart lib header dateien nicht inkludiert (visual studio findet die sonst irgnedwie). Ist zwar praktisch für den entwickler, aber für portierungen doof 🙂


  • Mod

    hustbaer schrieb:

    Schuss ins Blaue: versuch mal einen Typedef zu machen:

    namespace x
    {
    class A;
    
    class B
    {
    public:
    
        typedef A x_A;
    
        virtual x_A* A() = 0;
    };
    }
    

    Das hilft nicht. Im Allgemeinen kann ein Bezeichner außerhalb der Klasse, der durch einen gleichnamigen Bezeichner innerhalb der Klasse verdeckt wird, nicht unqualifiziert innerhalb der Klassendefinition oder der Definitionen/Deklaartionen seiner Member verwendet werden. Ausnahme wäre ggf. ein typedef, dass mit dem gleichen Namen auf den äußeren Bezeichner abbildet.

    3.3.6/2 schrieb:

    1. A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

Anmelden zum Antworten