[C ++] - herencia y derivación


Todos sabemos que la herencia es un potente lenguaje de programación orientada a objetos mecanismo, también sabemos que la relación entre clase y clase, hay dos
combinaciones: una parte de la relación ... una parte de la
herencia: una especie de ... una relación.
Este artículo, hablemos de eso ~

1. Sucesión

1. La esencia y el principio de la herencia.

La esencia de la herencia es en realidad la reutilización de código. El siguiente código, B hereda A

class A
{
public:
	int ma;
protected:
	int mb;
private:
	int mc;//只有自己或者友元能访问私有的成员
};
class B : A
{
public:
	int md;
	void fun()
	{
		cout << ma << endl;
	}
protected:
	int me;
private:
	int mf;
};

La relación entre las clases A y B se muestra en la figura:
Inserte la descripción de la imagen aquí
uso de la herencia para reutilizar ma, mb, mc en A (clase base, clase padre). El proceso de herencia también viene con alcance.

2. Herencia

La clase B hereda de la clase A. Existen tres métodos de herencia. Para las restricciones de acceso en la clase, hay métodos correspondientes como se muestra en la siguiente figura:
Inserte la descripción de la imagen aquí
A partir de esto, podemos resumir los métodos de herencia de la siguiente manera:

  1. Solo se puede acceder a los miembros del objeto público desde el exterior , mientras que a los miembros protegidos y privados no se puede acceder directamente
  2. En la estructura de la sucesión, clase derivada de una clase base puede heredar más de los miembros de la privada , pero la clase derivada, pero no se puede acceder directamente
  3. La diferencia entre protegido y privado en la clase base, los miembros definidos quieren que la clase derivada acceda a ellos pero no quieren que el exterior acceda a ellos , entonces en la clase base, los miembros relacionados se definen como protegidos.
    Si ni la clase derivada ni el plan externo tienen acceso , en la clase base, que se define como miembros de la opción de venta relacionado privada privada

El método de herencia predeterminado:
depende de si la clase derivada se define mediante class o struct.
Class define una clase derivada, el método de herencia predeterminado es privado , clas s define una clase derivada y el método de herencia predeterminado es público.

3. En la estructura de herencia, la conversión de arriba (clase base) a abajo (clase derivada)

Aún así, el código anterior, agregamos la función show para transformarlo de la siguiente manera:

class Base
{
public:
	Base(int data = 10) :ma(data) { }
	void show() { cout << "Base::show()" << endl; }//1
	void show(int) { cout << "Base::show(int)" << endl; }//2
protected:
	int ma;
};
class Derive :public Base
{
public:
	Derive(int data = 20)
		:Base(data), mb(data){}
	void show() { cout << "Derive::show()" << endl; }//3
private:
	int mb;
};

A continuación, debemos usar el código anterior para explorar las siguientes cuatro conversiones: Conversión de
objetos de clase base en objetos de clase derivados. Conversión de
objetos de clase derivados en objetos de clase base.
Punteros de clase base (referencias) a objetos de clase derivados.
Punteros de clase derivados (referencias) a Objeto de clase base

(1) Objeto de clase base b <-objeto derivado d

int main()
{
	Base b(10);
	Derive d(20);
	b = d;
	return 0;
}

Este método es equivalente a necesitar una persona y darle un maestro. Es una conversión de tipo de abajo hacia arriba. Es posible.

(2) Objeto derivado d <-base clase objeto b

int main()
{
	Base b(10);
	Derive d(20);
	d = b;
	return 0;
}

Este método es equivalente a un estudiante que hace matemáticas avanzadas, pero es imposible que una persona lo complete, y un tipo de proceso de arriba a abajo es imposible.

(3) Puntero de clase base (referencia) <objeto de clase derivada

int main()
{
	Base b(10);
	Derive d(20);
	Base* pb = &d;
	return 0;
}

De esta manera es una conversión de tipo de abajo hacia arriba, es posible . Pero el tipo de puntero es solo una clase base, que restringe el acceso solo a los miembros de la clase base parte de la clase derivada

Si desea acceder a los miembros de la clase derivada, debe realizar una conversión de tipo, de la siguiente manera:

((Derive*)pb)->show();

(4) Puntero de clase derivada (referencia) <objeto de clase base

int main()
{
	Base b(10);
	Derive d(20);
	Derive* pb = &b;
	return 0;
}

Esto no es posible , es un tipo de proceso de arriba hacia abajo.
Los siguientes métodos pueden resolver el problema, pero no es seguro e implica un acceso ilegal a la memoria

Resumen: en la estructura de herencia, la conversión de tipos de arriba a abajo es compatible de forma predeterminada, solo se admite la conversión de tipos de abajo a arriba

2. Derivación

1. ¿Cómo inicializan las clases derivadas las variables miembro heredadas de la clase base?

Antes de responder a esta pregunta, primero implementamos un código heredado, que contiene la inicialización del constructor.

class Base
{
public:
	Base(int data) :ma(data) { cout << "Base()" << endl; }
	~Base() { cout << "~Base()" << endl; }
protected:
	int ma;
};
class Derive :public Base
{
public:
	Derive(int data)
		:ma(data), mb(data) 
	{
		cout << "Derive()" << endl;
	}
	~Derive()
	{
		cout << "~Derive()" << endl;
	}
private:
	int mb;
};
int main()
{
	Derive d(20);
	return 0;
}

Pero observe cuidadosamente el código anterior, encontraremos que la inicialización de su constructor de objetos de clase derivada es incorrecta. Debido a que no existe un constructor predeterminado adecuado para la clase base, los miembros de la clase base no se pueden inicializar en la clase derivada.

Por lo tanto, debemos cambiar el proceso de inicialización del constructor del objeto de clase derivado de la siguiente manera:

Derive(int data)
		:Base(data), mb(data)
	{
		cout << "Derive()" << endl;
	}

Inicialice llamando al constructor correspondiente de la clase base. La
clase derivada puede heredar todos los miembros (variables y métodos) de la clase base , eliminar el constructor y el destructor (porque estos dos son significativos en la clase actual)
. Y el destructor es responsable de inicializar y limpiar la parte de la clase derivada. La inicialización y limpieza de los miembros de la clase derivada heredada de la clase base es responsable de la construcción y la desestructuración de la clase base.

2. El proceso de construcción y destrucción de objetos derivados.

  1. La clase derivada llama al constructor de la clase base para inicializar los miembros heredados de la acumulación.

  2. Llame al constructor de la clase derivada para inicializar sus propios miembros únicos.

... El alcance del objeto de clase derivada ha expirado

  1. Llame al destructor de la clase derivada para liberar recursos externos (memoria de almacenamiento dinámico, archivos) que pueden estar ocupados por miembros de la clase derivada
  2. Llame al destructor de la clase base para liberar los recursos externos (memoria de almacenamiento dinámico, archivos) que pueden estar ocupados por miembros heredados de la clase base en la memoria de la clase derivada

Como se muestra a continuación:

Inserte la descripción de la imagen aquí

3. Alcance oculto de la clase derivada

¿Recuerda el código de este punto de conocimiento desde la parte superior (clase base) hasta la parte inferior (clase derivada) en la estructura de herencia que mencionamos anteriormente?
Si usa la función show de la siguiente manera en la función principal, obtendrá un error

int main()
{
	Derive d;
	d.show();
	d.show(10);
	return 0;
}

La función "Derivar :: show ()" no acepta el error del parámetro 1, porque el show de clase derivada está oculto del alcance de show de la clase base, y la prioridad es encontrar los miembros del nombre del show del alcance de la clase derivada. Busque en la clase base, puede usar los siguientes métodos para corregir

d.Base::show(10);

Por lo tanto, se puede concluir que en el mecanismo de herencia, los miembros del mismo nombre de la clase derivada ocultan miembros del mismo nombre de la clase base. Esta ocultación es una relación de ocultación del alcance.

Publicado 98 artículos originales · ganado elogios 9 · vistas 3665

Supongo que te gusta

Origin blog.csdn.net/qq_43412060/article/details/105195932
Recomendado
Clasificación