O resumo mais básico de C++ orientado a objetos

Suplemento: modelo de partição de memória

Pilha: alocada e recuperada pelo compilador para armazenar variáveis ​​locais e parâmetros de funções.
Heap: Gerenciado pelo programador, precisa ser alocado e recuperado manualmente pelo novo malloc delete free.O espaço é grande, mas podem ocorrer vazamentos de memória e fragmentos livres.
Área de armazenamento global/estática: Dividida em duas áreas adjacentes, inicializada e não inicializada, para armazenar variáveis ​​globais inicializadas e não inicializadas e variáveis ​​estáticas.
Área de armazenamento constante: armazena constantes, geralmente não é permitido modificar.
Área de código: armazena o código binário do programa.

Quando um programa C++ é executado, a direção geral da memória é dividida em 4 áreas
Área de código: armazena o código binário do corpo da função, gerenciado pelo sistema operacional Área global
: armazena variáveis ​​globais e variáveis ​​estáticas e
área de pilha constante: automaticamente alocado pelo compilador Release, armazena valores de parâmetros de função, variáveis ​​locais, etc.
Área heap: alocado e liberado pelo programador, caso o programador não libere, será recuperado pelo sistema operacional ao final do programa

O significado das quatro áreas da memória:
os dados armazenados em diferentes áreas, dotados de diferentes ciclos de vida, nos dão maior flexibilidade
Resumo da programação:
C++ é dividido em área global e área de código antes da execução do programa.
A área de código é caracterizada por compartilhamento e área global somente leitura
Armazena variáveis ​​globais, variáveis ​​estáticas e constantes
Armazena constantes globais const-modificadas e constantes de string na área constante

sobrecarga de funções

Função: Os nomes das funções podem ser os mesmos para melhorar a capacidade de reutilização. Incorpora polimorfismo em tempo de compilação
A sobrecarga de função satisfaz as condições:
sob o mesmo escopo (a função com o mesmo nome na mesma classe, está sobrecarregada)
o nome da função é o mesmo
, o tipo de parâmetro da função é diferente ou o número é diferente ou a ordem é diferente (não se preocupe com o tipo de valor de retorno)

1. Classes e Objetos

1 Descreva resumidamente o que é orientação a objetos

A orientação a objetos é um tipo de ideia de programação. Ela considera tudo como um objeto e empacota as variáveis ​​de atributos pertencentes a esses objetos e as funções que operam essas variáveis ​​de atributos em uma classe para representar

A diferença entre orientado a processo e orientado a objeto Orientado
a processo: escrever código de cima para baixo de acordo com a lógica de negócios
Orientado a objeto: vincular dados e funções, encapsula-los , acelerar o desenvolvimento de programas e reduzir o processo de reescrita de códigos repetidos.
Por exemplo,
classe de soquete do Windows classe de janela
classe de nuvem de pontos PointCloud, opencv
cv::Point2i, cv::Point2f, cv::Point2d, cv::Point3i, cv::Point3f, cv::Point3d. As
três principais características do objeto -orientados são encapsulamento, herança, polimorfismo.

Encapsulamento: combine organicamente os dados e o método de manipulação dos dados, oculte as propriedades e os detalhes de implementação do objeto e apenas exponha a interface para interagir com o objeto. O encapsulamento é essencialmente um tipo de gerenciamento.Se não quisermos que outros vejam, usamos protected/private para encapsular os membros. Abra algumas funções de membros públicos para acesso razoável aos membros.

Herança: você pode usar todos os membros de dados e funções de membro de função de classes existentes e estender essas funções sem reescrever a classe original.

Polimorfismo: Use o ponteiro do tipo pai para apontar para uma instância de sua subclasse e, em seguida, chame a função de membro da subclasse real por meio do ponteiro da classe pai. Existem duas maneiras de atingir o polimorfismo, reescrevendo e sobrecarregando.

C++ pensatudo é um objeto, com suas propriedades e comportamento no 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;
}

Inicialização e limpeza de objetos construtores e destruidores

Construtor: A função principal é atribuir valores às propriedades membro do objeto ao criar o objeto. O construtor é chamado automaticamente pelo compilador sem chamada manual
.
Destruidor: A principal função é que o sistema chame automaticamente antes que o objeto seja destruído para realizar algum trabalho de limpeza.

C++ usa construtores e destruidores para resolver os problemas acima.Essas duas funções serão chamadas automaticamente pelo compilador para concluir a inicialização e limpeza do objeto.
A inicialização e a limpeza do objeto são coisas que o compilador nos obriga a fazer, portanto, se não fornecermos construção e destruição, o compilador o fará.

Construtores e destruidores fornecidos pelo compilador são implementações vazias.

A classe A vazia sizeof(A) instanciará um objeto do tipo A. Para determinar o endereço exclusivo, retorne 1 byte
contendo apenas funções de membro comuns ou destruidores e retorne 1 com o construtor

Funções de membro comuns na classe não participam das estatísticas de sizeof(). Destrutores, funções-membro como construtores, não têm nada a ver com sizeof, e não é difícil de entender porque nosso sizeof é para instâncias, enquanto funções-membro comuns são para corpos de classe. Uma função-membro de uma classe, várias instâncias também compartilham o mesmo ponteiro de função, portanto, naturalmente, não pode ser atribuído ao tamanho da instância.

insira a descrição da imagem aqui

A classe vazia não fornece construção e destruição, o compilador fornecerá o construtor e o destruidor fornecido pelo compilador é uma implementação vazia

Por padrão, o compilador c++ adiciona pelo menos 3 funções a uma classe
1. Construtor padrão (sem parâmetros, o corpo da função está vazio)
2. Destruidor padrão (sem parâmetros, o corpo da função está vazio)
3. O construtor de cópia padrão, que copia o valor da propriedade
e também fornece um operador de atribuição

As regras para chamar construtores são as seguintes:
Se o usuário definir um construtor parametrizado, C++ não fornecerá mais o construtor padrão sem argumentos, mas fornecerá o construtor de cópia padrão
Se o usuário definir um construtor de cópia, C++ não fornecerá outros construtores

Quais funções de membro de classe são geradas por padrão em uma classe vazia em C++

O compilador c++ adiciona pelo menos 6 funções a uma classe

1. Construtor padrão (sem parâmetros, o corpo da função está vazio)
2. Destruidor padrão (sem parâmetros, o corpo da função está vazio)
3. Construtor de cópia padrão, copie o valor do atributo (cópia superficial)

4. Função de sobrecarga do operador de atribuição, cópia de valor (cópia superficial) do atributo
5. Função de sobrecarga do operador de valor
6. Função de sobrecarga do operador de valor const

Se houver um atributo na classe apontando para a área de heap (como um membro de ponteiro na classe), também haverá um problema de cópia profunda e superficial ao fazer operações de atribuição

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

Somente quando você precisar usar essas funções, o compilador irá defini-las?
insira a descrição da imagem aqui

cópia profunda vs cópia rasa

* Exemplo típico, a classe contém um membro ponteiro int p;
este é o construtor de cópia que deve ser escrito manualmente quando necessário

Cópia rasa: operação de cópia de atribuição simples. Copiar apenas uma cópia de uma variável de ponteiro p
pode fazer com que o mesmo ponteiro seja liberado duas vezes
Cópia profunda: reaplica espaço na área de heap e copia o objeto apontado pelo ponteiro 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 inicialização

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

Objetos de classe são usados ​​como membros de classe para examinar a ordem de construção e destruição

https://blog.csdn.net/weixin_39731083/article/details/81903997
2. Ordem de invocação dos construtores
Construtor de classe base, construtor de membro de objeto, construtor da própria classe derivada

  1. A ordem de chamada do destruidor é
    o destruidor da própria classe derivada, o destruidor de membro de objeto e o destruidor de classe base (a ordem de construção é exatamente o oposto)

4. Caso especial
Objeto local, destruído ao sair do bloco de programa

Objeto estático, destruído no final do arquivo em que está definido

Objeto global, destruído no final do programa

Objetos de herança, primeiro destrua a classe derivada e depois destrua a classe pai

Membros de objeto, primeiro destrua o objeto de classe e, em seguida, destrua os membros de objeto

4.2.8 Membros Estáticos

O membro estático deve adicionar a palavra-chave static antes da variável de membro e da função de membro, chamada de membro 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; //私有权限访问不到

Os membros estáticos são divididos em:
Variáveis ​​de membros estáticos
Todos os objetos compartilham os mesmos dados
A memória é alocada durante a fase de compilação Declaração dentro da classe, funções de membros estáticos
inicializadas fora da classe Todos os objetos compartilham a mesma função, que só pode ser acessada chamando o static função de membro por meio do nome da classe ou do nome do objeto Variáveis ​​de membro estáticas e funções de membro estáticas não podem retornar o próprio objeto


4.3 Modelo de objeto C++ e este ponteiro Em C++, variáveis ​​de membro e funções de membro em uma classe são armazenadas separadamente

Em C++, as variáveis ​​de membro e as funções de membro na classe são armazenadas separadamente
(o código da função de membro deve estar na área de código de qualquer maneira??)

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

este conceito de ponteiro

Como as variáveis ​​de membro e as funções de membro em C++ são armazenadas separadamente,
cada função de membro não estática gerará apenas uma instância de função, ou seja, vários objetos do mesmo tipo compartilharão um pedaço de código, então a questão é
: como distinguir este pedaço de código daquele E quanto ao objeto chamando a si mesmo? Este ponteiro
esta função de membro não estática de ponteiro usa este ponteiro para distinguir qual objeto está chamando a si mesmo.
O ponteiro this aponta para o objeto ao qual pertence a função-membro chamada.O ponteiro this é um ponteiro implícito
em cada função-membro não estática .

O objetivo do ponteiro this explícito:
1. Quando o parâmetro formal e a variável de membro têm o mesmo nome, o ponteiro this pode ser usado para distinguir
2. Para retornar o próprio objeto na função de membro não estática da classe , você pode usar return *this

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 função de membro modificada const

Não há lugar para const, a posição na frente da função é ocupada por static/inline, então só pode ser colocada atrás da função, O(∩_∩)O haha~

Função constante:
Depois de adicionar const após a função de membro, chamamos essa função de função constante. O
atributo de membro não pode ser modificado na função constante.
Depois que a palavra-chave mutable é adicionada quando o atributo de membro é declarado,
o objeto constante ainda pode ser modificado na função constante:
adicione const antes da declaração do objeto O objeto é chamado de objeto constante.Um
objeto constante só pode chamar funções 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**

Um amigo é apenas uma declaração, é absolutamente impossível ser membro desta classe

O propósito de um amigo é declarar uma função ou classe como um amigo desta classe, e
eles podem acessar os membros privados desta classe

Três implementações de amigos
Funções globais como amigos
Classes como amigos
Funções de membros como amigos

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

4.5 Sobrecarga do operador

Conceito de sobrecarga do operador: redefina os operadores existentes e dê a eles outra função para se adaptar a diferentes tipos de dados

4.6 Herança

As classes em C++ têm três direitos de acesso (também chamados de controle de acesso), que são públicos, protegidos e privados

insira a descrição da imagem aqui
insira a descrição da imagem aqui

Conceito 1: Estático
Os níveis de acesso dos membros de uma classe em C++ podem ser divididos em público, protegido e privado. Público tem o nível mais baixo de acesso e pode ser acessado por qualquer pessoa.
As variáveis ​​de membro público e funções de membro de uma classe podem ser acessadas por meio de funções de membro e variáveis ​​de instância da classe. O
nível de acesso protegido é médio. As variáveis ​​de membro protegidas e funções de membro de uma classe não podem ser acessadas por meio de variáveis ​​de instância do aula. Mas pode ser acessado através da função amigo e da classe amigo da classe.
O nível de acesso privado é o mais alto. As variáveis ​​de membro privado e as funções de membro de uma classe não podem ser acessadas por meio das variáveis ​​de instância da classe. Mas pode ser acessado através da função amigo e da classe amigo da classe.
Até agora descobrimos que não parece haver grande diferença entre protegido e privado, mas a principal diferença está no segundo conceito.
Conceito 2: Dinâmico
Sobre o dinâmico, ou seja, o significado da ação. Ele contém relacionamentos de herança pai-filho. Ou seja, como a autoclasse herda a classe pai, seja herança pública, herança protegida ou herança privada.
(1) Herança pública
As classes derivadas são herdadas por meio do público e várias permissões da classe base permanecem inalteradas.
As funções de membro da classe derivada podem acessar os membros públicos e protegidos da classe base, mas não podem acessar os membros privados da classe base.
As variáveis ​​de instância da classe derivada podem acessar os membros públicos da classe base, mas não podem acessar os membros protegidos e privados, como se os membros da classe base fossem adicionados à classe derivada.
A herança pública pode ser considerada como uma classe derivada que inclui os membros públicos e protegidos da classe base para a classe derivada, mas não inclui membros privados.
(2) herança protegida
A classe derivada é herdada por meio de protegida e as permissões dos membros públicos da classe base na classe derivada tornam-se protegidas. protegidos e privados permanecem inalterados.
As funções de membro da classe derivada podem acessar os membros públicos e protegidos da classe base, mas não podem acessar os membros privados da classe base.
As variáveis ​​de instância da classe derivada não podem acessar nenhum membro da classe base, porque os membros públicos da classe base ficam protegidos na classe derivada.
A herança protegida pode ser considerada como uma classe derivada que inclui os membros públicos e protegidos da classe base na classe derivada, todos os quais são membros protegidos da classe derivada, mas os membros privados não estão incluídos.
O membro privado é a privacidade dentro da classe base, exceto para amigos, todos os funcionários não têm permissão para espionar. Os amigos da classe derivada não podem ser acessados
​​(3)
herança privada A classe derivada é herdada por meio de private e as permissões de todos os membros da classe base na classe derivada tornam-se privadas.
As funções de membro da classe derivada podem acessar os membros públicos e protegidos da classe base, mas não podem acessar os membros privados da classe base.
As variáveis ​​de instância da classe derivada não podem acessar nenhum membro da classe base, porque todos os membros da classe base se tornam privados na classe derivada.
A herança privada pode ser considerada como uma classe derivada que inclui os membros públicos e protegidos da classe base na classe derivada, todos os quais são membros privados da classe derivada, mas os membros privados não estão incluídos.
O membro privado é a privacidade dentro da classe base, exceto para amigos, todos os funcionários não têm permissão para espionar. Amigos de classes derivadas não podem ser acessados

Benefícios da herança: == pode reduzir código duplicado

class A : public B; 

A classe A é chamada de classe filha ou classe derivada A classe
B é chamada de classe pai ou classe base

Os membros da classe derivada incluem duas partes :
uma é herdada da classe base e a outra são os membros adicionados.
Os herdados da classe base mostram sua semelhança, enquanto os membros recém-adicionados refletem sua individualidade.

Ordem de construção e destruição

https://blog.csdn.net/weixin_39731083/article/details/81903997
2. Ordem de chamada dos construtores
Construtores de classe base, construtores de membros de objeto, construtores das próprias classes derivadas
3. Ordem de chamada de
classes derivadas de destruidores Destruidor próprio, destruidor de membro de objeto , destruidor de classe base (na ordem inversa da construção)

4.6.5 Herança de sócios com o mesmo nome

Overload (overload) Override (override) (função virtual, reescrever???) 3. Overwrite (overwrite)

https://www.cnblogs.com/kuliuheng/p/4107012.html
1.
O conceito de Overload (sobrecarga) é melhor compreendido. No mesmo escopo de declaração de classe (no mesmo escopo), múltiplas Duas funções com exatamente o mesmo nome, mas parâmetros diferentes (tipo ou número) são chamados de Sobrecarga. As características da sobrecarga são as seguintes:
(1) O mesmo escopo (na mesma classe);
(2) O nome da função é o mesmo;
(3) Os parâmetros são diferentes;
(4) A palavra-chave virtual é opcional.

2. Override ((função virtual, reescrever???)
O conceito de Override é realmente usado para realizar o polimorfismo C++, ou seja, a função virtual
reescreve a função declarada como virtual na classe pai na subclasse . Quando o programa está em execução , De acordo com o tipo de objeto, é julgado se deve chamar a função de mesmo nome na classe pai ou na classe
Exemplo típico , na classe pai, geralmente é necessário declarar o destruidor como uma função virtual. Para evitar vazamentos de memória
, porque no programa, o ponteiro do tipo de classe pai é usado Apontando para o objeto da subclasse, o destruidor da classe pai deve ser declarado como uma função virtual.

As características de Override são as seguintes:
(1) Escopos diferentes (localizados na classe derivada e na classe base, respectivamente);
(2) O nome da função é o mesmo;
(3) A lista de parâmetros é exatamente a mesma;
(4) A função de classe base deve ter a chave virtual Character.

3. Sobrescrever (reescrever)
A função na classe pai não é declarada como uma função virtual e a função com o mesmo nome é reescrita na subclasse

Reescrever significa que a função da classe derivada protege (ou "oculta") a função da classe base com o mesmo nome. É essa regra oculta do C++ que faz aumentar repentinamente a complexidade do problema, que se divide em duas situações para discussão:

(1) Se a função da classe derivada tiver o mesmo nome da função da classe base, mas os parâmetros forem diferentes. Então, neste momento, independentemente de haver uma palavra-chave virtual, a função da classe base ficará oculta (cuidado para não confundir com sobrecarga).
(2) Se a função da classe derivada tiver o mesmo nome e os mesmos parâmetros que a função da classe base, mas a função da classe base não tiver a palavra-chave virtual. Então, neste momento, as funções da classe base ficam ocultas (cuidado para não confundir com 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 Herança de membros estáticos com o mesmo nome

Descrição: Como membros estáticos com o mesmo nome na herança podem ser acessados ​​em objetos de subclasse?
Membros estáticos e membros não estáticos com o mesmo nome são tratados da mesma maneira

  • O acesso aos membros da subclasse com o mesmo nome pode ser acessado diretamente
  • Para acessar membros com o mesmo nome da classe pai, você precisa adicionar o escopo da classe pai
//同名成员属性
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 Sintaxe de herança múltipla

C++ permite que uma classe herde várias classes
Gramática: class 子类 :继承方式 父类1 , 继承方式 父类2...
Herança múltipla pode fazer com que membros com o mesmo nome apareçam na classe pai, e escopo precisa ser adicionado para diferenciá-lo.
No desenvolvimento real de C++, não é recomendado usar vários herança

//语法: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 Herança Diamante

Nota: classe base virtual

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

Resumir:

  • O principal problema causado pela herança diamante é que as subclasses herdam duas cópias dos mesmos dados, resultando em desperdício de recursos e falta de sentido
  • O uso de herança virtual pode resolver o problema de herança de diamante, garantindo que haja apenas uma cópia dos dados na classe base virtual

4.7 Polimorfismo

O polimorfismo é um dos três principais recursos orientados a objetos do C++**
O polimorfismo é dividido em dois tipos de
polimorfismo estático: sobrecarga de função e sobrecarga de operador são polimorfismo estático, nome da função de reutilização (sobrecarga)
polimorfismo dinâmico: classe derivada e função virtual Realize o tempo de execução polimorfismo (a palavra-chave override é usada com funções virtuais virtuais)

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

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

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

A diferença entre polimorfismo estático e polimorfismo dinâmico:

  • Ligação antecipada do endereço da função polimórfica estática - determine o endereço da função durante a compilação
  • Associação tardia do endereço da função polimórfica dinâmica - o tempo de execução determina o endereço da função
//我们希望传入什么对象,那么就调用什么对象的函数
//如果函数地址在编译阶段就能确定,那么静态联编
//如果函数地址在运行阶段才能确定,就是动态联编
总结
//多态满足条件: 
//1、有继承关系
//2、子类重写父类中的虚函数
//多态使用:
//父类指针或引用指向子类对象

4.7.3 Funções virtuais puras e classes abstratas (ou chamadas classes virtuais puras)

Diferença: classe abstrata (função virtual pura) e classe base virtual (herança virtual)

No polimorfismo, a implementação de funções virtuais na classe pai geralmente não tem sentido, principalmente chamando o conteúdo reescrito pela subclasse. Portanto, a função
virtual pode ser alterada para uma função virtual pura
. Sintaxe da função virtual pura: virtual 返回值类型 函数名 (参数列表)= 0 ;
quando uma classe tem um valor puro função virtual, esta classe também é chamadaclasse abstrata
Características da classe abstrata:

  • Não foi possível instanciar o objeto
  • A subclasse deve substituir a função virtual pura na classe abstrata, caso contrário, ela também pertence à classe abstrata
class Base
{
    
    
public:
	//纯虚函数
	//类中只要有一个纯虚函数就称为抽象类
	//抽象类无法实例化对象
	//子类必须重写父类中的纯虚函数,否则也属于抽象类
	virtual void func() = 0;
};

4.7.5 Destruição virtual e virtual pura

O problema causado pelo ponteiro da classe pai apontando para o objeto da subclasse

Ao usar o polimorfismo, se houver atributos na subclasse que são alocados para a área de heap, o ponteiro da classe pai chamará o código destruidor da classe pai quando for liberado e o código destruidor da subclasse não poderá ser chamado
. a definição do destruidor foi alterada para destruidor virtual ou destruidor virtual puro.
Sintaxe do destruidor virtual:
virtual ~类名(){}
sintaxe do destruidor virtual puro:
virtual ~类名() = 0;
`nome da classe::~nome da classe(){}

1. Destruidor virtual ou destruidor virtual puro é usado para resolver o problema de liberar objetos de subclasse por meio de ponteiros de classe pai.
2. Se não houver dados de heap na subclasse, ela não pode ser escrita como destruidor virtual ou destruidor virtual puro
. 3 .Possuir uma classe pura com um destruidor virtual também é uma classe abstrata

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 fluxo de operação de arquivo

É um pensamento orientado a objetos;
os dados gerados quando o programa está em execução são todos dados temporários e serão liberados assim que o programa terminar de ser executado. Os dados podem ser persistidos por meio do arquivo. Em C++, a operação do arquivo precisa incluir o cabeçalho arquivo<fstream>

Existem dois tipos de arquivo:

  1. Arquivos de texto - os arquivos são armazenados em seu computador como texto em ASCII
  2. Arquivos binários - os arquivos são armazenados no computador em forma de texto binário e os usuários geralmente não podem lê-los diretamente

Três tipos de operações de arquivo:
3. ofstream: operação de gravação
4. ifstream: operação de leitura
5. fstream: operações de leitura e gravação

Acho que você gosta

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