c++ - simple - Especificador de acceso de herencia predeterminado
que es herencia simple y multiple (9)
Si tengo, por ejemplo, dos clases A
y B
, de modo que la clase B
hereda A
siguiente manera:
class B: public A
En este caso, estoy haciendo herencia public
.
Si escribo el código anterior de la siguiente manera:
class B: A
¿Qué tipo de herencia estaré haciendo aquí (es decir, público)? En otras palabras, ¿cuál es el especificador de acceso predeterminado?
Solo una pregunta secundaria aquí. ¿Llamo a la línea anterior de statements
de códigos? Especialmente que recuerdo que leí en el libro C ++ Without Fear: A Beginner''s Guide That Makes You Feel Smart que las statements
son las que terminan con eso ;
. ¿Qué piensas sobre eso?
Gracias.
COMO OTRO PROBLEMA DE LANZAMIENTO TIENES
class A { virtual void test() = 0; };
class B : virtual public A { virtual void testb() {} };
class C : virtual public A { virtual void testc() {} };
class D : public B, public C {
virtual void test() override {}
}
void main() {
D d;
void* v = &d;
A* a = &d;
((D*)A)->test(); //OK
((D*)v)->test(); //undefined behavior (that call testb() in vtable logic at 1st inheritance position)
dynamic_cast<D*>(v)->test(); //compile error cast from void* not permitted
//resolution
void* x = a;
((D*)x)->test(); //OK but as you can see, you must to store a* in x*
}
Cuando heredas una clase de otra clase, el especificador de acceso predeterminado es privado.
#include <stdio.h>
class Base {
public:
int x;
};
class Derived : Base { }; // is equilalent to class Derived : private Base {}
int main()
{
Derived d;
d.x = 20; // compiler error becuase inheritance is private
getchar();
return 0;
}
Cuando hereda una estructura de otra clase, el especificador de acceso predeterminado es público.
#include < stdio.h >
class Base {
public:
int x;
};
struct Derived: Base {}; // is equilalent to struct Derived : public Base {}
int main() {
Derived d;
d.x = 20; // works fine becuase inheritance is public
getchar();
return 0;
}
El "tipo" de herencia depende de cómo se define la clase. Hay especificadores de acceso predeterminados aplicados a la herencia. Desde el estándar C ++:
En ausencia de un especificador de acceso para una clase base, se asume público cuando la clase derivada se define con la
struct
clave de clase y se asume privada cuando la clase se define con la clase de clave declass
. [Ejemplo:
class B { /* ... */ }; class D1 : private B { /* ... */ }; class D2 : public B { /* ... */ }; class D3 : B { /* ... */ }; // B private by default struct D4 : public B { /* ... */ }; struct D5 : private B { /* ... */ }; struct D6 : B { /* ... */ }; // B public by default class D7 : protected B { /* ... */ }; struct D8 : protected B { /* ... */ };
Aquí B es una base pública de D2, D4 y D6, una base privada de D1, D3 y D5, y una base protegida de D7 y D8. - ejemplo final]
El tipo predeterminado de la herencia es privado en C ++.
class B:A
{};
es equivalente a
class B: private A
{};
Es privado para la clase y público para struct.
Respuesta lateral: No, estas son definiciones de la clase de acuerdo con el estándar.
Si no eliges una herencia, C ++ se convierte en herencia private
por defecto de la misma forma que los miembros de la clase tienen acceso private
a las clases por defecto.
Si usa la class
para definir su clase, el especificador de acceso predeterminado será private
. (Creo que también está mal.) Si usas struct
, sin embargo, será public
.
Y las definiciones de clase son declaraciones, creo. Una declaración es lo que se traduce en código real (a menos que esté optimizado de todos modos).
Sin embargo, una característica ligeramente exótica de C y C ++ es que las expresiones son enunciados. Es por eso que 3+4;
es una declaración sintácticamente legal en C ++ (aunque muchos compiladores advertirán que no tiene ningún efecto). Si bien es evidente que no tiene sentido en este caso, en general las expresiones se evalúan por sus efectos secundarios. (Un ejemplo obvio es descartar el valor de retorno de una función. Llama a la función no para obtener un resultado, sino para sus efectos secundarios).
Solo una pequeña adición a todas las respuestas existentes: el tipo predeterminado de la herencia depende del tipo heredado (B), no del que se hereda (A). Por ejemplo:
class A {};
struct B: /* public */ A {};
struct A {};
class B: /* private */ A {};
el especificador de acceso predeterminado es un importante diferenciador entre clases y estructuras. Es público por defecto para las estructuras y privado por defecto para las clases.