¿Se requiere un nombre de clase completo hasta el alcance global para las definiciones de funciones de miembros fuera de línea?

14

Esta pregunta me hizo preguntarme si alguna vez es útil / necesario calificar completamente los nombres de clase (incluido el operador de alcance global) en una definición de función de miembro fuera de clase.

Por un lado, nunca había visto esto antes (y la sintaxis para hacerlo correctamente parece oscura). Por otro lado, la búsqueda de nombres en C ++ no es muy trivial, por lo que tal vez exista un caso de esquina.

Pregunta:

¿Hay algún caso en el que la introducción de una definición de función miembro fuera de clase
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
difiera de
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... }(sin ::prefijo de alcance global )?

Tenga en cuenta que las definiciones de funciones miembro deben colocarse en un espacio de nombres que encierra la clase, por lo que este no es un ejemplo válido.

Max Langhof
fuente
Muy curioso lo que no le gusta al votante sobre esta pregunta. Comentarios bienvenidos!
Max Langhof
cuando la definición se coloca en un espacio de nombres diferente al de la declaración? Eso es lo que tenía en mente para el quesiton vincula
IDCLEV 463035818
oops, no leí la letra pequeña;)
idclev 463035818
@ formerlyknownas_463035818 Eso es también lo que tenía en mente, luego lo probé y me di cuenta de que no funcionaría, así que escribí la pregunta (suponiendo que otros también se preguntarían).
Max Langhof

Respuestas:

12

Una directiva de uso puede hacer Fullyque sea ambigua sin calificación.

namespace Foo {
    struct X {
    };
}

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

void X::c() { } // ambiguous
void ::X::c() { } // OK
TC
fuente
5

Es necesario si uno es masoquista y le gusta escribir cosas como esta

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

   struct bar {
       void baz();
   };

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

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

Por supuesto, se puede escribir la segunda sobrecarga como foo::foo::bar::bazen el ámbito global, pero la pregunta era si las dos declaraciones pueden tener un significado diferente. No recomendaría escribir ese código.

StoryTeller - Unslander Monica
fuente
Sí, esta es una respuesta válida, y ni siquiera necesita una using. ¡Es bueno tener diferentes casos resaltados!
Max Langhof
2

Si se usa una directiva using, puede haber un código confuso.

Considere el siguiente programa demostrativo

#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;
}

Entonces, para facilitar la lectura, este nombre calificado

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

muestra con precisión dónde se declara la función.

Vlad de Moscú
fuente