declaración using

La declaración using introduce un nombre en la región declarativa en la que aparece la declaración "using".

Sintaxis

using [typename] nested-name-specifier unqualified-id ;
using declarator-list ;

Parámetros

nested-name-specifier Secuencia de espacios de nombres, clases o nombres de enumeración y operadores de resolución de ámbito (::), terminados mediante un operador de resolución de ámbito. Se puede usar un único operador de resolución de ámbito para introducir un nombre del espacio de nombres global. La palabra clave typename es opcional y se puede usar para resolver los nombres dependientes cuando se introducen en una plantilla de clase desde una clase base.

unqualified-id Una expresión id-expression no habilitada, que puede ser un identificador, un nombre de operador sobrecargado, un operador literal definido por el usuario o un nombre de función de conversión, un nombre de destructor de clase o un nombre de plantilla y una lista de argumentos.

declarator-list Una lista separada por comas de declaradores [typename] nested-name-specifierunqualified-id, seguido opcionalmente por puntos suspensivos.

Comentarios

Una declaración "using" introduce un nombre no habilitado como sinónimo de una entidad declarada en otro lugar. Permite usar un único nombre obtenido de un espacio de nombres específico sin necesidad de una habilitación explícita en la región de declaración en la que aparece. Esto contrasta con la directiva "using", que permite utilizar sin habilitación todos los nombres de un espacio de nombres. La palabra clave using se utiliza también para los alias de tipo.

Ejemplo: declaración using en el campo de clase

Se puede utilizar una declaración using en una definición de clase.

// using_declaration1.cpp
#include <stdio.h>
class B {
public:
   void f(char) {
      printf_s("In B::f()\n");
   }

   void g(char) {
      printf_s("In B::g()\n");
   }
};

class D : B {
public:
   using B::f;    // B::f(char) is now visible as D::f(char)
   using B::g;    // B::g(char) is now visible as D::g(char)
   void f(int) {
      printf_s("In D::f()\n");
      f('c');     // Invokes B::f(char) instead of recursing
   }

   void g(int) {
      printf_s("In D::g()\n");
      g('c');     // Invokes B::g(char) instead of recursing
   }
};

int main() {
   D myD;
   myD.f(1);
   myD.g('a');
}
In D::f()
In B::f()
In B::g()

Ejemplo: declaración using para declarar un miembro

Cuando se utiliza para declarar un miembro, una declaración using debe hacer referencia a un miembro de una clase base.

// using_declaration2.cpp
#include <stdio.h>

class B {
public:
   void f(char) {
      printf_s("In B::f()\n");
   }

   void g(char) {
      printf_s("In B::g()\n");
   }
};

class C {
public:
   int g();
};

class D2 : public B {
public:
   using B::f;   // ok: B is a base of D2
   // using C::g;   // error: C isn't a base of D2
};

int main() {
   D2 MyD2;
   MyD2.f('a');
}
In B::f()

Ejemplo: declaración using con habilitación explícita

Se puede hacer referencia a miembros declarados con una declaración using mediante una habilitación explícita. El prefijo :: hace referencia al espacio de nombres global.

// using_declaration3.cpp
#include <stdio.h>

void f() {
   printf_s("In f\n");
}

namespace A {
   void g() {
      printf_s("In A::g\n");
   }
}

namespace X {
   using ::f;   // global f is also visible as X::f
   using A::g;   // A's g is now visible as X::g
}

void h() {
   printf_s("In h\n");
   X::f();   // calls ::f
   X::g();   // calls A::g
}

int main() {
   h();
}
In h
In f
In A::g

Ejemplo: sinónimos y alias de declaración using

Cuando se crea una declaración using, el sinónimo creado por la declaración solo hace referencia a las definiciones que son válidas en el lugar de la declaración using. Las definiciones que se agregan a un espacio de nombres después de la declaración using no son sinónimos válidos.

Un nombre definido por una declaración using es un alias para su nombre original. No afecta al tipo, la vinculación u otros atributos de la declaración original.

// post_declaration_namespace_additions.cpp
// compile with: /c
namespace A {
   void f(int) {}
}

using A::f;   // f is a synonym for A::f(int) only

namespace A {
   void f(char) {}
}

void f() {
   f('a');   // refers to A::f(int), even though A::f(char) exists
}

void b() {
   using A::f;   // refers to A::f(int) AND A::f(char)
   f('a');   // calls A::f(char);
}

Ejemplo: declaraciones locales y declaraciones using

En cuanto a las funciones de espacios de nombres, si se proporciona un conjunto de declaraciones locales y declaraciones using para un único nombre en una región declarativa, todas ellas deben hacer referencia a la misma entidad o todas ellas deben hacer referencia a funciones.

// functions_in_namespaces1.cpp
// C2874 expected
namespace B {
    int i;
    void f(int);
    void f(double);
}

void g() {
    int i;
    using B::i;   // error: i declared twice
    void f(char);
    using B::f;   // ok: each f is a function
}

En el ejemplo anterior, la instrucción using B::i hace que se declare un segundo int i en la función g(). La instrucción using B::f no entra en conflicto con la función f(char) porque los nombres de función introducidos por B::f tienen distintos tipos de parámetro.

Ejemplo: declaraciones de función locales y declaraciones using

Una declaración de función local no puede tener el mismo nombre y tipo que una función introducida mediante una declaración using. Por ejemplo:

// functions_in_namespaces2.cpp
// C2668 expected
namespace B {
    void f(int);
    void f(double);
}

namespace C {
    void f(int);
    void f(double);
    void f(char);
}

void h() {
    using B::f;          // introduces B::f(int) and B::f(double)
    using C::f;          // C::f(int), C::f(double), and C::f(char)
    f('h');              // calls C::f(char)
    f(1);                // C2668 ambiguous: B::f(int) or C::f(int)?
    void f(int);         // C2883 conflicts with B::f(int) and C::f(int)
}

Ejemplo: declaración using y herencia

Con respecto a la herencia, cuando una declaración using introduce un nombre de una clase base en el ámbito de una clase derivada, las funciones miembro de la clase derivada invalidan las funciones de miembro virtual que tienen los mismos nombres y tipos de argumento en la clase base.

// using_declaration_inheritance1.cpp
#include <stdio.h>
struct B {
   virtual void f(int) {
      printf_s("In B::f(int)\n");
   }

   virtual void f(char) {
      printf_s("In B::f(char)\n");
   }

   void g(int) {
      printf_s("In B::g\n");
   }

   void h(int);
};

struct D : B {
   using B::f;
   void f(int) {   // ok: D::f(int) overrides B::f(int)
      printf_s("In D::f(int)\n");
   }

   using B::g;
   void g(char) {   // ok: there is no B::g(char)
      printf_s("In D::g(char)\n");
   }

   using B::h;
   void h(int) {}   // Note: D::h(int) hides non-virtual B::h(int)
};

void f(D* pd) {
   pd->f(1);     // calls D::f(int)
   pd->f('a');   // calls B::f(char)
   pd->g(1);     // calls B::g(int)
   pd->g('a');   // calls D::g(char)
}

int main() {
   D * myd = new D();
   f(myd);
}
In D::f(int)
In B::f(char)
In B::g
In D::g(char)

Ejemplo: accesibilidad a la declaración using

Todas las instancias de un nombre mencionado en una declaración using deben ser accesibles. En concreto, si una clase derivada utiliza una declaración using para tener acceso a un miembro de una clase base, el nombre de miembro debe ser accesible. Si el nombre es el de una función miembro sobrecargada, todas las funciones enumeradas deben ser accesibles.

Consulte Control de acceso a miembros para más información sobre la accesibilidad de los miembros.

// using_declaration_inheritance2.cpp
// C2876 expected
class A {
private:
   void f(char);
public:
   void f(int);
protected:
   void g();
};

class B : public A {
   using A::f;   // C2876: A::f(char) is inaccessible
public:
   using A::g;   // B::g is a public synonym for A::g
};

Consulte también

Espacios de nombres
Palabras clave