Czy w przypadku definicji funkcji członka poza linią wymagana jest w pełni kwalifikowana nazwa klasy do zasięgu globalnego?

14

To pytanie sprawiło, że zastanawiałem się, czy kiedykolwiek przydatne / konieczne jest pełne kwalifikowanie nazw klas (w tym operatora zasięgu globalnego) w definicji funkcji członka poza klasą.

Z jednej strony nigdy wcześniej tego nie widziałem (a składnia, aby to zrobić, wydaje się niejasna). Z drugiej strony wyszukiwanie nazw w C ++ jest bardzo nietrywialne, więc może istnieje przypadek narożny.

Pytanie:

Czy kiedykolwiek zdarza się, że wprowadzenie pozaklasowej definicji funkcji członka
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
różni się od
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... }(brak ::prefiksu zasięgu globalnego )?

Należy pamiętać, że definicje funkcji członek musi być wprowadzane do otaczającej przestrzeni nazw klasy, więc to nie jest poprawnym przykładem.

Max Langhof
źródło
Bardzo ciekawe, co downvoter nie lubi w tym pytaniu. Witamy mile widziane!
Max Langhof,
kiedy definicja jest umieszczona w innym obszarze nazw niż deklaracja? Właśnie to miałem na myśli przy
pytaniu, które łączysz
Ups, nie przeczytałem małego odcisku;)
idclev 463035818,
@ previouslyknownas_463035818 To też miałem na myśli, a potem spróbowałem i zdałem sobie sprawę, że to nie zadziała, więc napisałem pytanie (myśląc, że inni też by się zastanawiali).
Max Langhof,

Odpowiedzi:

12

Użyciu dyrektywą może powodować Fullybyć niejednoznaczne bez kwalifikacji.

namespace Foo {
    struct X {
    };
}

using namespace Foo;
struct X {
    void c();
};

void X::c() { } // ambiguous
void ::X::c() { } // OK
TC
źródło
5

Jest to konieczne, jeśli ktoś jest masochistą i lubi pisać takie rzeczy

namespace foo {
    namespace foo {
        struct bar {
            void baz();
        };
    }

   struct bar {
       void baz();
   };

   void foo::bar::baz() {
   }

   void (::foo::bar::baz)() {
   }
} 

Drugie przeciążenie można oczywiście napisać jak foo::foo::bar::bazw zakresie globalnym, ale pytanie brzmiało, czy te dwie deklaracje mogą mieć inne znaczenie. Nie polecałbym pisania takiego kodu.

StoryTeller - Unslander Monica
źródło
Tak, to jest rzeczywiście poprawna odpowiedź i nawet nie potrzebuje using. Miło mieć różne przypadki podświetlone!
Max Langhof,
2

Jeśli używana jest dyrektywa używająca, kod może być mylący.

Rozważ następujący program demonstracyjny

#include <iostream>
#include <string>

namespace N1
{
    struct A
    {
        void f() const;
    };      
}

using namespace N1;

void A::f() const { std::cout << "N1::f()\n"; }

struct A
{
    void f() const;
};

void ::A::f() const { std::cout << "::f()\n"; }

int main() 
{
    N1::A().f();
    ::A().f();

    return 0;
}

Więc dla czytelności ta kwalifikowana nazwa

void ::A::f() const { std::cout << "::f()\n"; }

pokazuje dokładnie, gdzie funkcja jest zadeklarowana.

Vlad z Moskwy
źródło