El resumen más básico de C++ orientado a objetos

Suplemento: modelo de partición de memoria

Pila: asignada y recuperada por el compilador para almacenar variables locales y parámetros de funciones.
Heap: Administrado por el programador, debe ser asignado y recuperado manualmente por new malloc delete free.El espacio es grande, pero pueden ocurrir fugas de memoria y fragmentos libres.
Área de almacenamiento global/estática: Dividida en dos áreas adyacentes, inicializadas y no inicializadas, para almacenar variables globales inicializadas y no inicializadas y variables estáticas.
Área de almacenamiento constante: almacena constantes, generalmente no se permite modificar.
Área de código: almacena el código binario del programa.

Cuando se ejecuta un programa en C++, la dirección general de la memoria se divide en 4 áreas
Área de código: almacena el código binario del cuerpo de la función, administrado por el sistema operativo
Área global: almacena variables globales y variables estáticas y constantes
Área de pila: automáticamente asignado por el compilador Liberación, almacenar valores de parámetros de funciones, variables locales, etc.
Área de montón: asignada y liberada por el programador, si el programador no libera, será recuperada por el sistema operativo al final del programa

El significado de las cuatro áreas de memoria:
los datos almacenados en diferentes áreas, dotados de diferentes ciclos de vida, lo que nos brinda una mayor flexibilidad
Resumen de programación:
C ++ se divide en área global y área de código antes de que se ejecute el programa.
El área de código se caracteriza por compartir y área global de solo lectura
Almacene variables globales, variables estáticas y constantes
Almacene constantes globales y constantes de cadena modificadas const en el área constante

sobrecarga de funciones

Función: los nombres de las funciones pueden ser los mismos para mejorar la reutilización. Incorpora polimorfismo en tiempo de compilación.
La función de sobrecarga cumple las condiciones:
bajo el mismo ámbito (la función con el mismo nombre en la misma clase, está sobrecargada)
el nombre de la función es el mismo
, el tipo de parámetro de la función es diferente o el número es diferente o el orden es diferente (no importa el tipo de valor devuelto)

1. Clases y Objetos

1 Describa brevemente qué es la orientación a objetos

Orientado a objetos es un tipo de idea de programación. Considera todo como un objeto y empaqueta las variables de atributo que pertenecen a estos objetos y las funciones que operan estas variables de atributo en una clase para representar

La diferencia entre orientado a procesos y orientado a objetos Orientado
a procesos: escriba código de arriba a abajo de acuerdo con la lógica empresarial
Orientado a objetos: enlace datos y funciones, encapsúlelos , acelere el desarrollo de programas y reduzca el proceso de reescritura de códigos repetidos.
Por ejemplo,
clase de ventana de socket de Windows,
clase de nube de puntos, clase PointCloud, opencv
cv::Point2i, cv::Point2f, cv::Point2d, cv::Point3i, cv::Point3f, cv::Point3d. Las
tres características principales del objeto -orientados son Encapsulación, herencia, polimorfismo.

Encapsulación: combine orgánicamente los datos y el método de manipulación de los datos, oculte las propiedades y los detalles de implementación del objeto, y solo exponga la interfaz para interactuar con el objeto. La encapsulación es esencialmente un tipo de administración. Si no queremos que otros lo vean, usamos protected/private para encapsular a los miembros. Abra algunas funciones de miembros públicos para un acceso razonable a los miembros.

Herencia: puede usar todas las funciones de miembros de funciones y miembros de datos de las clases existentes y ampliar estas funciones sin volver a escribir la clase original.

Polimorfismo: use el puntero del tipo principal para señalar una instancia de su subclase y luego llame a la función miembro de la subclase real a través del puntero de la clase principal. Hay dos formas de lograr el polimorfismo, la reescritura y la sobrecarga.

C++ piensatodo es un objeto, con sus propiedades y comportamiento en el objeto

//圆周率
# PI 3.14
const double PI = 3.14;
//1、封装的意义
//将属性和行为作为一个整体,用来表现生活中的事物
//封装一个圆类,求圆的周长
//class代表设计一个类,后面跟着的是类名
class Circle
{
    
    
//访问权限,默认 私有的
//属性
int m_r;//半径
//行为
//获取到圆的周长
public:
double calculateZC()
{
    
    
//2 * pi
* r
//获取圆的周长
return
2 * PI * m_r;
}
};
int main() {
    
    
//通过圆类,创建圆的对象
// c1就是一个具体的圆
Circle c1;
c1.m_r = 10; //给圆对象的半径 进行赋值操作
//2 * pi * 10 = = 62.8
cout << "圆的周长为: " << c1.calculateZC() << endl;system("pause");
return 0;
}

Inicialización y limpieza de objetos constructores y destructores.

Constructor: la función principal es asignar valores a las propiedades miembro del objeto al crear el objeto. El compilador llama automáticamente al constructor sin una llamada manual
.
Destructor: La función principal es que el sistema llame automáticamente antes de que el objeto sea destruido para realizar algún trabajo de limpieza.

C++ utiliza constructores y destructores para resolver los problemas anteriores. El compilador llamará automáticamente a estas dos funciones para completar la inicialización y limpieza del objeto.
La inicialización y limpieza de objetos son cosas que el compilador nos obliga a hacer, por lo que si no proporcionamos la construcción y destrucción, el compilador lo hará.

Los constructores y destructores proporcionados por el compilador son implementaciones vacías.

La clase A vacía sizeof(A) creará una instancia de un objeto de tipo A. Para determinar la dirección única, devuelva 1 byte
que contenga solo funciones miembro ordinarias o destructores, y devuelva 1 con el constructor

Las funciones miembro ordinarias de la clase no participan en las estadísticas de sizeof(). Los destructores, las funciones miembro como los constructores, no tienen nada que ver con sizeof, y no es difícil de entender porque nuestro tamaño de es para instancias, mientras que las funciones miembro ordinarias son para cuerpos de clase. mismo puntero de función, por lo que, naturalmente, no se puede atribuir al tamaño de la instancia.

inserte la descripción de la imagen aquí

La clase vacía no proporciona construcción y destrucción, el compilador proporcionará el constructor y el destructor proporcionado por el compilador es una implementación vacía

De forma predeterminada, el compilador de c ++ agrega al menos 3 funciones a una clase
1. Constructor predeterminado (sin parámetros, el cuerpo de la función está vacío)
2. Destructor predeterminado (sin parámetros, el cuerpo de la función está vacío)
3. El constructor de copia predeterminado, que copia el valor de la propiedad
y también proporciona un operador de asignación

Las reglas para llamar a los constructores son las siguientes:
Si el usuario define un constructor parametrizado, C++ ya no proporcionará el constructor predeterminado sin argumentos, pero proporcionará el constructor de copia predeterminado.
Si el usuario define un constructor de copia, C++ no proporcionará otros constructores.

Qué funciones miembro de clase se generan de forma predeterminada en una clase vacía en C++

El compilador de c++ agrega al menos 6 funciones a una clase

1. Constructor predeterminado (sin parámetros, el cuerpo de la función está vacío)
2. Destructor predeterminado (sin parámetros, el cuerpo de la función está vacío)
3. Constructor de copia predeterminado, copia el valor del atributo (copia superficial)

4. Función de sobrecarga del operador de asignación, copia de valor (copia superficial) del atributo
5. Función de sobrecarga del operador de valor
6. Función de sobrecarga del operador de valor constante

Si hay un atributo en la clase que apunta al área del montón (como un miembro puntero en la clase), también habrá un problema de copia profunda y superficial al realizar operaciones de asignación.

class Empty
{
    
    
public:
Empty(); // 缺省构造函数//
Empty( const Empty& ); // 拷贝构造函数//
~Empty(); // 析构函数//
Empty& operator=( const Empty& ); // 赋值运算符//
Empty* operator&(); // 取址运算符
const Empty* operator&() const; // 取址运算符 const
};

¿Solo cuando necesite usar estas funciones, el compilador las definirá?
inserte la descripción de la imagen aquí

copia profunda vs copia superficial

* Ejemplo típico, la clase contiene un miembro puntero int p;
este es el constructor de copia que debe escribirse manualmente cuando sea necesario

Copia superficial: operación de copia de asignación simple. Solo copiar una copia de una variable de puntero p
puede hacer que el mismo puntero se suelte dos veces
Copia profunda: vuelva a aplicar espacio en el área del montón y copie el objeto al que apunta el puntero p.

https://blog.csdn.net/wue1206/article/details/81138097

class Test
{
    
    
private:
    int* p;
public:
    Test(int x)
    {
    
    
        this->p=new int(x);
        cout << "对象被创建" << endl;
    }
    ~Test()
    {
    
    
        if (p != NULL)
        {
    
    
            delete p;
        }
        cout << "对象被释放" << endl;
    }
    int getX() {
    
     return *p; }
    //深拷贝(拷贝构造函数)
    Test(const Test& a)
    {
    
    
        this->p = new int(*a.p);
        cout << "对象被创建" << endl;
    }
    //浅拷贝(拷贝构造函数)
    //Test(const Test& a)
    //{
    
    
    //  this->p = a.p;
    //  cout << "对象被创建" << endl;
    //}
};

int main()
{
    
    
    Test a(10);
    //我们手动的写拷贝构造函数,C++编译器会调用我们手动写的
    Test b = a;
    return 0;
}

lista de inicialización

Person p(1, 2, 3);
p.PrintPerson();

Los objetos de clase se utilizan como miembros de clase para examinar el orden de construcción y destrucción.

https://blog.csdn.net/weixin_39731083/article/details/81903997
2. Orden de invocación de los constructores
Constructor de clase base, constructor de miembro de objeto, constructor de la propia clase derivada

  1. El orden de llamada del destructor es
    el destructor de la clase derivada en sí, el destructor del miembro del objeto y el destructor de la clase base (el orden de construcción es exactamente el opuesto)

4. Caso especial
Objeto local, destruido al salir del bloque de programa

Objeto estático, destruido al final del archivo en el que se define

Objeto global, destruido al final del programa

Objetos de herencia, primero destruya la clase derivada y luego destruya la clase principal

Miembros del objeto, primero destruya el objeto de la clase y luego destruya los miembros del objeto

4.2.8 Miembros estáticos

El miembro estático es agregar la palabra clave estática antes de la variable miembro y la función miembro, llamada miembro estático

//静态成员变量两种访问方式
//1、通过对象
Person p1;
p1.m_A = 100;
cout << "p1.m_A = " << p1.m_A << endl;
Person p2;
p2.m_A = 200;
cout << "p1.m_A = " << p1.m_A << endl; //共享同一份数据
cout << "p2.m_A = " << p2.m_A << endl;
//2、通过类名
cout << "m_A = " << Person::m_A << endl;
//cout << "m_B = " << Person::m_B << endl; //私有权限访问不到

Los miembros estáticos se dividen en:
Variables miembro estáticas
Todos los objetos comparten los mismos datos
La memoria se asigna durante la fase de compilación Declaración dentro de la clase, funciones miembro estáticas
inicializadas fuera de la clase Todos los objetos comparten la misma función, a la que solo se puede acceder llamando a la función estática función miembro a través del nombre de la clase o el nombre del objeto Las variables miembro estáticas y las funciones miembro estáticas no pueden devolver el objeto en sí


4.3 Modelo de objetos de C++ y este puntero En C++, las variables miembro y las funciones miembro de una clase se almacenan por separado

En C++, las variables miembro y las funciones miembro de la clase se almacenan por separado
(¿el código de la función miembro debería estar en el área de código de todos modos?)

只有非静态成员变量才属于类的对象的内存上,占用对象的内存空间

este concepto de puntero

Debido a que las variables miembro y las funciones miembro en C++ se almacenan por separado,
cada función miembro no estática solo generará una instancia de función, es decir, varios objetos del mismo tipo compartirán un fragmento de código, por lo que la pregunta es
: cómo distinguir esta pieza de código de esa ¿Qué pasa con el objeto que se llama a sí mismo? Este puntero
esta función de miembro no estático de puntero utiliza este puntero para distinguir qué objeto se está llamando a sí mismo.
El puntero this apunta al objeto al que pertenece la función miembro llamada. El puntero this es un puntero implícito
en cada función miembro no estática .

El propósito del puntero this explícito:
1. Cuando el parámetro formal y la variable miembro tienen el mismo nombre, el puntero this se puede usar para distinguir
2. Para devolver el objeto en sí mismo en la función miembro no estática de la clase , usted puede usar regresar *esto

class Person
{
    
    
public:
Person(int age)
{
    
    
//1、当形参和成员变量同名时,可用this指针来区分
this->age = age;
}
Person& PersonAddPerson(Person p)
{
    
    
this->age += p.age;
//返回对象本身
return *this;
}
int age;
};
void test01()
{
    
    
	Person p1(10);
	cout << "p1.age = " << p1.age << endl;
	Person p2(10);
	p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);
	cout << "p2.age = " << p2.age << endl;
}
int main() {
    
    
	test01();
	system("pause");
	return 0;
}

4.3.4 función miembro modificada const

No hay lugar para const, la posición frente a la función está ocupada por static/inline, por lo que solo se puede colocar detrás de la función, O(∩_∩)O jaja~

Función constante:
después de agregar const después de la función miembro, llamamos a esta función una función constante. El
atributo miembro no se puede modificar en la función constante.
Después de agregar la palabra clave mutable cuando se declara el atributo miembro,
el objeto constante aún se puede modificar en la función constante:
agregue const antes de la declaración del objeto El objeto se llama un objeto constante
Un objeto constante solo puede llamar funciones constantes.

class Person {
    
    
public:
	Person() {
    
    
		m_A = 0;
		m_B = 0;
	}

	//this指针的本质是一个指针常量,指针的指向不可修改
	//如果想让指针指向的值也不可以修改,需要声明常函数
	void ShowPerson() const {
    
    
		//const Type* const pointer;
		//this = NULL; //不能修改指针的指向 Person* const this;
		//this->mA = 100; //但是this指针指向的对象的数据是可以修改的

		//const修饰成员函数,表示指针指向的内存空间的数据不能修改,除了mutable修饰的变量
		this->m_B = 100;
	}

	void MyFunc() const {
    
    
		//mA = 10000;
	}

public:
	int m_A;
	mutable int m_B; //可修改 可变的
};


//const修饰对象  常对象
void test01() {
    
    

	const Person person; //常量对象  
	cout << person.m_A << endl;
	//person.mA = 100; //常对象不能修改成员变量的值,但是可以访问
	person.m_B = 100; //但是常对象可以修改mutable修饰成员变量

	//常对象访问成员函数
	person.MyFunc(); //常对象不能调用const的函数

}

int main() {
    
    

	test01();

	system("pause");

	return 0;
}

**4.4 Amigos**

Un amigo es solo una declaración, es absolutamente imposible ser miembro de esta clase.

El propósito de un amigo es declarar una función o clase como amigo de esta clase, y
pueden acceder a los miembros privados de esta clase.

Tres implementaciones de amigos
Funciones globales como amigos
Clases como amigos
Funciones de miembros como amigos

friend void goodGay(Building * building);
friend class goodGay;
friend void goodGay::visit();

4.5 Sobrecarga del operador

Concepto de sobrecarga de operadores: redefine los operadores existentes y dales otra función para adaptarse a diferentes tipos de datos

4.6 Herencia

Las clases en C++ tienen tres derechos de acceso (también llamados control de acceso), que son públicos, protegidos y privados.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Concepto 1: estático
Los niveles de acceso de los miembros de una clase en C++ se pueden dividir en público, protegido y privado. Público tiene el nivel más bajo de acceso y cualquiera puede acceder a él.
Se puede acceder a las variables miembro públicas y las funciones miembro de una clase a través de las funciones miembro y las variables de instancia de la clase. El
nivel de acceso protegido es medio. No se puede acceder a las variables miembro protegidas y las funciones miembro de una clase a través de las variables de instancia de la clase. clase. Pero se puede acceder a través de la función de amigo y la clase de amigo de la clase.
El nivel de acceso privado es el más alto. Las variables miembro privadas y las funciones miembro de una clase no se pueden acceder a través de las variables de instancia de la clase. Pero se puede acceder a través de la función de amigo y la clase de amigo de la clase.
Hasta ahora hemos encontrado que no parece haber una gran diferencia entre protegido y privado, pero la principal diferencia radica en el segundo concepto.
Concepto 2: Dinámico
Sobre dinámico, es decir, el sentido de la acción. Contiene relaciones de herencia padre-hijo. Es decir, cómo la autoclase hereda la clase principal, ya sea herencia pública, herencia protegida o herencia privada.
(1) Herencia pública
Las clases derivadas se heredan a través de público y varios permisos de la clase base permanecen sin cambios.
Las funciones miembro de la clase derivada pueden acceder a los miembros públicos y protegidos de la clase base, pero no pueden acceder a los miembros privados de la clase base.
Las variables de instancia de la clase derivada pueden acceder a los miembros públicos de la clase base, pero no pueden acceder a los miembros protegidos y privados, como si los miembros de la clase base se agregaran a la clase derivada.
La herencia pública se puede considerar como una clase derivada que incluye los miembros públicos y protegidos de la clase base a la clase derivada, pero no incluye los miembros privados.
(2) herencia protegida
La clase derivada se hereda a través de protected y los permisos de los miembros públicos de la clase base en la clase derivada se protegen. protegido y privado permanecen sin cambios.
Las funciones miembro de la clase derivada pueden acceder a los miembros públicos y protegidos de la clase base, pero no pueden acceder a los miembros privados de la clase base.
Las variables de instancia de la clase derivada no pueden acceder a ningún miembro de la clase base, porque los miembros públicos de la clase base quedan protegidos en la clase derivada.
La herencia protegida se puede considerar como una clase derivada que incluye los miembros públicos y protegidos de la clase base en la clase derivada, todos los cuales son miembros protegidos de la clase derivada, pero los miembros privados no están incluidos.
El miembro privado es la privacidad dentro de la clase base, a excepción de los amigos, todo el personal no puede espiar. No se puede acceder a los amigos de la clase derivada
(3)
herencia privada La clase derivada se hereda a través de privado, y los permisos de todos los miembros de la clase base en la clase derivada se vuelven privados.
Las funciones miembro de la clase derivada pueden acceder a los miembros públicos y protegidos de la clase base, pero no pueden acceder a los miembros privados de la clase base.
Las variables de instancia de la clase derivada no pueden acceder a ningún miembro de la clase base, porque todos los miembros de la clase base se vuelven privados en la clase derivada.
La herencia privada se puede considerar como una clase derivada que incluye los miembros públicos y protegidos de la clase base en la clase derivada, todos los cuales son miembros privados de la clase derivada, pero los miembros privados no están incluidos.
El miembro privado es la privacidad dentro de la clase base, a excepción de los amigos, todo el personal no puede espiar. No se puede acceder a amigos de clases derivadas

Beneficios de la herencia: == puede reducir el código duplicado

class A : public B; 

La clase A se denomina clase secundaria o clase derivada. La clase
B se denomina clase principal o clase base.

Los miembros de la clase derivada incluyen dos partes :
una se hereda de la clase base y la otra son los miembros agregados.
Los heredados de la clase base muestran su similitud, mientras que los miembros recién agregados reflejan su individualidad.

Orden de construcción y destrucción

https://blog.csdn.net/weixin_39731083/article/details/81903997
2. Orden de llamada de constructores
Constructores de clase base, constructores de miembros de objetos, constructores de clases derivadas
3. Orden de llamada de destructores
clases derivadas Destructor propio, destructor de miembros de objetos , destructor de clase base (en orden inverso de construcción)

4.6.5 Herencia de miembros con el mismo nombre

Sobrecarga (sobrecarga) Anulación (anulación) (función virtual, ¿reescribir?) 3. Sobrescribir (sobrescribir)

https://www.cnblogs.com/kuliuheng/p/4107012.html
1.
El concepto de sobrecarga (sobrecarga) se entiende mejor. En el mismo ámbito de declaración de clase (en el mismo ámbito), varias funciones Dos con exactamente el mismo nombre pero diferentes parámetros (tipo o número) se denominan Sobrecarga. Las características de la sobrecarga son las siguientes:
(1) El mismo alcance (en la misma clase);
(2) El nombre de la función es el mismo;
(3) Los parámetros son diferentes;
(4) La palabra clave virtual es opcional.

2. Anular ((función virtual, ¿reescribir???)
El concepto de anular se usa realmente para realizar el polimorfismo de C++, es decir, la función virtual
reescribe la función declarada como virtual en la clase principal en la subclase . Cuando el programa se está ejecutando , Según el tipo de objeto, se juzga si llamar a la función del mismo nombre en la clase padre o en la clase.Ejemplo
típico , en la clase padre, generalmente es necesario declarar el destructor como una función virtual. Para evitar pérdidas de memoria
, ya que en el programa se utiliza el puntero del tipo de clase principal que apunta al objeto de la subclase, el destructor de la clase principal debe declararse como una función virtual.

Las características de Override son las siguientes:
(1) Diferentes ámbitos (ubicados en la clase derivada y la clase base respectivamente);
(2) El nombre de la función es el mismo;
(3) La lista de parámetros es exactamente la misma;
(4) La función de clase base debe tener el carácter de clave virtual.

3. Sobrescribir (reescribir)
La función en la clase principal no se declara como una función virtual, y la función con el mismo nombre se reescribe en la subclase

Reescribir significa que la función de la clase derivada protege (u "oculta") la función de la clase base con el mismo nombre. Es esta regla oculta de C++ la que hace que aumente repentinamente la complejidad del problema, que se divide en dos situaciones a discutir:

(1) Si la función de la clase derivada tiene el mismo nombre que la función de la clase base, pero los parámetros son diferentes. Entonces en este momento, independientemente de si hay una palabra clave virtual, la función de la clase base estará oculta (cuidado de no confundirla con sobrecarga).
(2) Si la función de la clase derivada tiene el mismo nombre y los mismos parámetros que la función de la clase base, pero la función de la clase base no tiene la palabra clave virtual. Entonces, en este momento, las funciones de la clase base están ocultas (tenga cuidado de no confundir con cobertura).

class Base{
    
    
public:
    virtual int fcn();
};
class Derived1:public Base{
    
    
public:
    //隐藏基类的fcn,这个fcn不是虚函数
    //Derived1继承了Base::fcn()的定义
    int fcn(int);         //形参类别与Base中的fcn不一样
    virtual void f2();    //是一个新的虚函数,在Base中不存在
};
class Derived2:public D1{
    
    
publicint fcn(int);        //是一个非虚函数,隐藏了Derived1::fcn(int)
    int fcn();           //覆盖了Base的虚函数fcn
    void f2();           //覆盖了Derived1的虚函数f2

4.6.6 Herencia de miembros estáticos con el mismo nombre

Pregunta: ¿Cómo se puede acceder a miembros estáticos con el mismo nombre en herencia en objetos de subclase?
Los miembros estáticos y no estáticos con el mismo nombre se manejan de la misma manera

  • Se puede acceder directamente a los miembros de la subclase con el mismo nombre
  • Para acceder a miembros con el mismo nombre de la clase principal, debe agregar el alcance de la clase principal
//同名成员属性
void test01()
{
    
    
	//通过对象访问
	cout << "通过对象访问: " << endl;
	Son s;
	cout << "Son  下 m_A = " << s.m_A << endl;
	cout << "Base 下 m_A = " << s.Base::m_A << endl;

	//通过类名访问
	cout << "通过类名访问: " << endl;
	cout << "Son  下 m_A = " << Son::m_A << endl;
	cout << "Base 下 m_A = " << Son::Base::m_A << endl;
}

4.6.7 Sintaxis de herencia múltiple

C++ permite que una clase herede varias clases
Gramática: class 子类 :继承方式 父类1 , 继承方式 父类2...
la herencia múltiple puede hacer que aparezcan miembros con el mismo nombre en la clase principal, y es necesario agregar un alcance para distinguirlo.
En el desarrollo real de C++, no se recomienda usar múltiples herencia

//语法:class 子类:继承方式 父类1 ,继承方式 父类2 
class Son : public Base2, public Base1 
{
    
    
public:
	Son()
	{
    
    
		m_C = 300;
		m_D = 400;
	}
public:
	int m_C;
	int m_D;
};

4.6.8 Herencia de diamantes

Nota: clase base virtual

//继承前加virtual关键字后,变为虚继承
//此时公共的父类Animal称为虚基类
class Sheep : virtual public Animal {
    
    };
class Tuo   : virtual public Animal {
    
    };
class SheepTuo : public Sheep, public Tuo {
    
    };

Resumir:

  • El principal problema causado por la herencia de diamantes es que las subclases heredan dos copias de los mismos datos, lo que genera un desperdicio de recursos y falta de sentido.
  • El uso de la herencia virtual puede resolver el problema de la herencia de diamantes, asegurando que solo haya una copia de los datos en la clase base virtual

4.7 Polimorfismo

El polimorfismo es una de las tres características principales orientadas a objetos de C++** El
polimorfismo se divide en dos tipos de
polimorfismo estático: la sobrecarga de funciones y la sobrecarga de operadores son polimorfismos estáticos, reutilizar el nombre de la función (sobrecarga)
polimorfismo dinámico: clase derivada y función virtual Realice el tiempo de ejecución polimorfismo (la palabra clave override se usa con funciones virtuales virtuales)

override是C++11中的一个新的继承控制关键字。override确保在派生类中声明的重载函数跟基类的 virtual虚函数有相同的声明。

override明确地表示一个函数是对基类中一个虚函数的重载。更重要的是,它会检查基类虚函数和派生类中重载函数的签名不匹配问题。如果签名不匹配,编译器会发出错误信息。

override表示函数应当重写基类中的虚函数(用于派生类的虚函数中)

La diferencia entre polimorfismo estático y polimorfismo dinámico:

  • Enlace temprano de dirección de función polimórfica estática: determine la dirección de función durante la compilación
  • Enlace tardío de la dirección de la función polimórfica dinámica: el tiempo de ejecución determina la dirección de la función
//我们希望传入什么对象,那么就调用什么对象的函数
//如果函数地址在编译阶段就能确定,那么静态联编
//如果函数地址在运行阶段才能确定,就是动态联编
总结
//多态满足条件: 
//1、有继承关系
//2、子类重写父类中的虚函数
//多态使用:
//父类指针或引用指向子类对象

4.7.3 Funciones virtuales puras y clases abstractas (o llamadas clases virtuales puras)

Diferencia: clase abstracta (función virtual pura) y clase base virtual (herencia virtual)

En el polimorfismo, la implementación de funciones virtuales en la clase principal generalmente no tiene sentido, principalmente llamando al contenido reescrito por la subclase. Por lo tanto, la función
virtual se puede cambiar a una función virtual pura
. Sintaxis de función virtual pura: virtual 返回值类型 函数名 (参数列表)= 0 ;
cuando una clase tiene un función virtual, esta clase también se llamaclase abstracta
Características de la clase abstracta:

  • No se pudo instanciar el objeto
  • La subclase debe anular la función virtual pura en la clase abstracta, de lo contrario, también pertenece a la clase abstracta.
class Base
{
    
    
public:
	//纯虚函数
	//类中只要有一个纯虚函数就称为抽象类
	//抽象类无法实例化对象
	//子类必须重写父类中的纯虚函数,否则也属于抽象类
	virtual void func() = 0;
};

4.7.5 Destrucción virtual y virtual pura

El problema causado por el puntero de la clase principal que apunta al objeto de la subclase

Al usar el polimorfismo, si hay atributos en la subclase que se asignan al área del montón, entonces el puntero de la clase principal llamará al código destructor de la clase principal cuando se libere, y no se podrá llamar al código destructor de la subclase
. la definición del destructor se cambia a destructor virtual o destructor virtual puro
Sintaxis del destructor virtual:
virtual ~类名(){}
sintaxis del destructor virtual puro:
virtual ~类名() = 0;
`nombre de clase::~nombre de clase(){}

1. El destructor virtual o el destructor virtual puro se utilizan para resolver el problema de liberar objetos de la subclase a través de punteros de la clase principal.
2. Si no hay datos de montón en la subclase, no se puede escribir como destructor virtual o destructor virtual puro
. 3 Poseer una clase pura A con un destructor virtual también es una clase abstracta

class Animal {
    
    
public:
	Animal()
	{
    
    
		cout << "Animal 构造函数调用!" << endl;
	}
	virtual void Speak() = 0;
	//析构函数加上virtual关键字,变成虚析构函数
	//virtual ~Animal()
	//{
    
    
	//	cout << "Animal虚析构函数调用!" << endl;
	//}
	virtual ~Animal() = 0;
};

Animal::~Animal()
{
    
    
	cout << "Animal 纯虚析构函数调用!" << endl;
}

//和包含普通纯虚函数的类一样,包含了纯虚析构函数的类也是一个抽象类。不能够被实例化。

class Cat : public Animal {
    
    
public:
	Cat(string name)
	{
    
    
		cout << "Cat构造函数调用!" << endl;
		m_Name = new string(name);
	}
	virtual void Speak()
	{
    
    
		cout << *m_Name <<  "小猫在说话!" << endl;
	}
	~Cat()
	{
    
    
		cout << "Cat析构函数调用!" << endl;
		if (this->m_Name != NULL) {
    
    
			delete m_Name;
			m_Name = NULL;
		}
	}

public:
	string *m_Name;
};

void test01()
{
    
    
	Animal *animal = new Cat("Tom");
	animal->Speak();

	//通过父类指针去释放,会导致子类对象可能清理不干净,造成内存泄漏
	//怎么解决?给基类增加一个虚析构函数
	//虚析构函数就是用来解决通过父类指针释放子类对象
	delete animal;
}

int main() {
    
    

	test01();

	system("pause");

	return 0;
}

5 Objeto de flujo de operación de archivo

Es un pensamiento orientado a objetos;
los datos generados cuando el programa se está ejecutando son todos datos temporales y se liberarán una vez que el programa termine de ejecutarse. Los datos se pueden conservar a través del archivo. En C++, la operación del archivo debe incluir el encabezado archivo<fstream>

Hay dos tipos de archivos:

  1. Archivos de texto : los archivos se almacenan en su computadora como texto en ASCII
  2. Archivos binarios : los archivos se almacenan en la computadora en forma de texto binario y, por lo general, los usuarios no pueden leerlos directamente.

Tres tipos de operaciones de archivo:
3. ofstream: operación de escritura
4. ifstream: operación de lectura
5. fstream: operaciones de lectura y escritura

Supongo que te gusta

Origin blog.csdn.net/qq_46084757/article/details/127040345
Recomendado
Clasificación