c++ - para - ¿Por qué no puede funcionar un miembro protegido de llamada derivada en este código?
codigo en c para derivar un polinomio (4)
#include <iostream>
class Base
{
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingProtected(); // This does not compile
somethingProtected(); // But this is fine
}
};
int main()
{
Derived d;
d.somethingDerived();
return 0;
}
Pensé que tal vez solo los miembros protegidos de this
pueden ser utilizados y los miembros protegidos de otras instancias son inalcanzables.
Pero:
class Derived : public Base
{
public:
void somethingDerived(Derived& d)
{
d.somethingProtected(); // This compiles even though d is
// potentially a different instance
}
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
}
};
Me siento un poco mareado por esto, ya que he estado programando en C ++ durante un tiempo, pero no pude encontrar ninguna explicación para este comportamiento.
EDITAR:
No importa si es la misma o una instancia diferente:
int main()
{
Derived d1, d2; // Two different instances
d1.somethingDerived(d2); // This compiles fine
d1.somethingDerived(d1); // This compiles fine
return 0;
}
EDIT2:
Parece que cuando se trata de derechos de acceso, no importa en absoluto qué instancia de una clase se está utilizando:
class Base
{
public:
void something(Base& b) // Another instance
{
++b.a; // But can enter private members
}
private:
int a;
};
Aunque el control de acceso en C ++ funciona en base a clases (en lugar de hacerlo por instancia), el especificador de acceso protected
tiene algunas peculiaridades.
La especificación del lenguaje quiere garantizar que está accediendo a un miembro protegido de algún subobjeto base que pertenece a la clase derivada. Se supone que no puede acceder a los miembros protegidos de algunos objetos independientes no relacionados de tipo base. En particular, no puede acceder a miembros protegidos de objetos independientes de tipo base. Solo se le permite acceder a miembros protegidos de objetos base que están incrustados en objetos derivados como subobjetos base.
Por este motivo, debe acceder a los miembros protegidos a través de la sintaxis pointer->member
syntax, reference.member
o object.member
, donde el puntero / referencia / objeto se refiere a la clase derivada .
Esto significa que en su ejemplo, el miembro protegido somethingProtected()
no es accesible a través Base
objetos Base
, punteros Base *
o Base &
referencias, pero se puede acceder a través de objetos Derived *
, punteros Derived *
y Derived &
referencias. Su acceso simple somethingProtected()
protegido somethingProtected()
está permitido, ya que es solo una abreviatura de this->somethingProtected()
donde this
es de tipo Derived *
.
b.somethingProtected()
infringe los requisitos anteriores.
Tenga en cuenta que de acuerdo con las reglas anteriores en
void Derived::somethingDerived()
{
Base *b = this;
b->somethingProtected(); // ERROR
this->somethingProtected(); // OK
}
la primera llamada también fallará mientras que la segunda compilará, aunque ambas intenten acceder a la misma entidad.
Creo que tienes cierta confusión sobre cómo acceder a los miembros de la clase base. Es solo así:
class Derived : public Base
void drivedMethod() {
Base::baseMethod();
}
en su ejemplo, intenta acceder a un miembro protegido de otra instancia.
una instancia Derivada tendrá acceso a sus propios miembros protegidos, pero no a otros miembros protegidos de instancia de clase, esto es por diseño.
De hecho, el acceso a los miembros protegidos de otra clase, desde otros miembros de la instancia o desde la función principal, de hecho ambos están bajo acceso público ...
http://www.cplusplus.com/doc/tutorial/inheritance/ (busque la tabla de especificaciones de acceso para ver los diferentes niveles)
Ambos ejemplos demuestran lo mismo, por ejemplo:
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
aquí su clase derivada obtiene b como parámetro, por lo tanto, está obteniendo otra instancia de base, y como b.somethingProtected no es público, no cumplirá.
esto cumplirá:
void somethingDerived()
{
Base::somethingDerived();
su segundo ejemplo cumple bien porque está accediendo a un método público en otra clase d
> void somethingDerived(Base& b)
> {
> b.somethingProtected(); // This does not
> }
La clase Derived
solo puede acceder al miembro base protegido en objetos Derived
. No puede acceder al miembro en objetos que no son (necesariamente) Objetos Derived
. En los casos que fallan, está tratando de acceder al miembro a través de una Base &
, y dado que esto podría referirse a un objeto que no es Derived
, no se puede realizar el acceso.
Lo que has hecho es ilegal en C ++. Un objeto protegido no puede acceder a un miembro protegido. Solo las funciones miembro pueden acceder a miembros protegidos. protected
miembros protected
se comportan igual que los miembros privados, excepto cuando son heredados por una clase derivada. Considere el programa que se proporciona a continuación para comprender la diferencia entre los miembros privados, públicos y protegidos.
class Base
{
private:
void somethingPrivate()
{
std::cout << "sasa" << std::endl;
}
public:
void somethingPublic()
{
std::cout << "haha" << std::endl;
}
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingPublic(); // Works fine.
somethingProtected(); // This is also fine because accessed by member function.
//b.somethingProtected(); // Error. Called using object b.
//somethingPrivate(); // Error. The function is not inherited by Derived.
}
};