Pregunta

Por lo general, la declaración 'Usando' se usa para poner en alcance algunas funciones de miembros de las clases base que de otro modo estarían ocultas. Desde ese punto de vista, es solo un mecanismo para hacer que la información accesible sea más conveniente de usar.
Sin embargo: la declaración 'usando' también se puede usar para cambiar las restricciones de acceso (no solo para las funciones sino también para los atributos). Por ejemplo:

class C{
public:
  int a;
  void g(){ cout << "C:g()\n"; }
  C() : a(0){}
};

class D : public C{
private:
  using C::a;
  using C::g;
public:
  D() { a = 1; }
};

int main(void){
  D d;
  cout << d.a << endl;  //error: a is inaccessible
  C *cp = &d;
  cout << cp->a << endl; //works
  d.g();  //error: g is inaccessible
  cp->g();  //works
  return 0;
}

Creo que esta limitación del acceso en la clase derivada es realmente de nada de nada, porque siempre puede acceder a G () y un puntero a la clase base. Entonces, ¿no debería haber al menos algún tipo de advertencia de compilador? ¿O no sería aún mejor prohibir tal limitación de acceso por una clase derivada? La declaración de uso no es la única posibilidad de agregar restricciones para acceder. También podría hacerse anulando la función de una clase base y colocarla en una sección con más restricciones de acceso. ¿Hay algunos ejemplos razonables en los que realmente es un poco informal limitar el acceso de tal manera? Si no, no veo por qué debería permitirse.

Y otra cosa: al menos con G ++ el mismo código se compila bien sin la palabra 'usar'. Eso significa para el ejemplo anterior: es posible escribir c :: a; y c :: g; en lugar de usar c :: a; usando c :: g; ¿Es el primero solo un atajo para este último o hay algunas diferencias sutiles?

//EDITAR:
Entonces, de la discusión y las respuestas a continuación, mi conclusión sería:
- Se permite limitar las limitaciones de acceso en clases derivadas con herencia pública
- Hay ejemplos útiles en los que podría usarse
- Su uso puede causar un problema en combinación con plantillas (por ejemplo, una clase derivada no podría ser un parámetro válido para alguna clase/función de plantilla, aunque su base es)
- Un diseño de lenguaje más limpio no debe permitir tal uso
- El compilador podría al menos emitir algún tipo de advertencia

¿Fue útil?

Solución

Con respecto a su declaración sin using: Estos se llaman "declaraciones de acceso" y están en desuso. Aquí está el texto del estándar, de 11.3/1:

El acceso de un miembro de una clase base se puede cambiar en la clase derivada mencionando su ID calificado en la declaración de clase derivada. Tal mención se llama una declaración de acceso. El efecto de una declaración de acceso qualified-id; se define como equivalente a la declaración usingqualified-id; Nota al pie: las declaraciones de acceso están en desuso; miembro Usando declaraciones (7.3.3) Proporcione un mejor medio para hacer las mismas cosas. En versiones anteriores del lenguaje C ++, las declaraciones de acceso fueron más limitadas; fueron generalizados y se hicieron equivalentes a Usando declaraciones - Nota final

Yo diría que la mayoría de las veces no es bueno cambiar público miembros de privado o protegido miembros en la clase derivada, porque esto violará el principio de sustitución: ya sabes que una clase base tiene algunas funciones, y si te pones a una clase derivada, entonces tu suponer Esas funciones también se pueden llamar, porque la clase derivada es un base. Y como ya mencionó, este invariante ya se aplica de todos modos por el lenguaje que permite convertir (¡que funciona implícitamente!) A una referencia de clase base, o calificando el nombre de la función, y luego llamando a la función (entonces pública).

Si desea prohibir que alguien llame a un conjunto de funciones de la base, entonces creo que esto sugiere que la contención (o en casos raros, la herencia privada) es una mejor idea.

Otros consejos

Si bien la declaración de uso que mostró proporciona un mecanismo para cambiar el nivel de acceso (pero solo hacia abajo), ese no es el uso principal de la misma en tal contexto. Un contexto de uso está destinado principalmente a permitir el acceso a funciones que de otro modo se sombrearían desde la clase base debido a la mecánica del lenguaje. P.ej

class A {
public:
   void A();
   void B();
};

class B {
public:
   using A::B;
   void B(int); //This would shadow A::B if not for a using declaration
};

La declaracion

using C::a

trae "A" al alcance de nombres local para que luego pueda usar "A" para referirse a "C :: A"; Desde eso, "C :: A" y "A" son intercambiables siempre que no declare una variable local con el nombre "A".

La declaración no cambia los derechos de acceso; Puede acceder a "A" en la subclase solo porque "A" no es privado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top