Polimorfismo de C++(7)

polimorfismo polimorfismo 

1. Hay funciones virtuales en la clase principal.

2. Anule la función virtual de la clase principal en la subclase

3. La dirección del objeto de la subclase se asigna al puntero de la clase principal y la función virtual se utiliza a través del puntero.

#include <iostream>

using namespace std;

class A
{
public:
    virtual void func()
        cout<<"class A"<<endl;
};

class B
{
private:
    void func()
        cout<<"class B"<<endl;
};

int main()
{
    A *pa = new B;  // 输出class B
    pa->func();

    return 0;
}

La compatibilidad de asignaciones solo ocurre en relaciones públicas derivadas entre padres e hijos.

Los objetos de subclase se asignan a objetos de la clase principal.

Referencias asignadas por objetos de subclase a clases principales

La dirección del objeto de la subclase se asigna al puntero de la clase principal. 

#include <iostream>

using namespace std;

class Shape
{
public:
    Shape(int x, int y)
        :_x(x), _y(y)
    {}
    
    void draw()
    {
        cout<<"draw from "<<"("<<_x<<","<<_y<<")"<<endl; 
    }

protected:
    int _x;
    int _y;
};

class Circle:public Shape
{
public:
    Circle(int x, int y, int r)
        :Shape(x, y), _radius(r)
    {} 

    void draw()
    {
        cout<<"draw from "<<"("<<_x<<","<<_y<<")"<<endl; 
        cout<<"radius = "<<_radius<<endl;
    }
    
private:
    int _radius;
};

int main()
{
    Shape s(1, 2);
    s.draw();

    Circle c(3, 4, 5);
    c.draw();
    c.func();

    s = c;
    s.draw();

    return 0;
}

Polimorfismo estático: determinado durante la compilación.

Polimorfismo dinámico: determinado en tiempo de ejecución.

polimorfismo

1. Hay una función virtual en la clase principal y la función virtual se declara virtual.

2. La función virtual de la clase principal se anula en la subclase.

3. Asigne la dirección del objeto de la subclase al puntero de la clase principal y llame a la función virtual.

#include <iostream>

using namespace std;

class Shape
{
public:
    Shape(int x, int y)
        :_x(x), _y(y)
    {}
    
    virtual void draw();

protected:
    int _x;
    int _y;
};

class Circle:public Shape
{
public:
    Circle(int x, int y, int r)
        :Shape(x, y), _radius(r)
    {} 

    virtual void draw()
    {
        cout<<"draw from "<<"("<<_x<<","<<_y<<")"<<endl; 
        cout<<"radius = "<<_radius<<endl;
    }
    
private:
    int _radius;
};

void Shape::draw
{
    cout<<"draw from "<<"("<<_x<<","<<_y<<")"<<endl; 
}

class Rect:public Shape
{
public:
    Rect(int x, int y, int len, int wid)
        :Shape(x, y), _len(len), _wid(wid)
    {}

    virtual void draw()
    {
        cout<<"start from "<<"("<<x<<","<<y<<")"<<endl;
        cout<<" len = "<<_len<<" wid = "<<_wid<<endl;
    }

private:
    int _len;
    int _wid;
};

int main()
{
    Circle c(3, 4, 5);
    c.draw();

    Shape *ps;

    //Shape *p = &c;
    // p->draw();

    // p = new Rect(3, 4, 5, 6);
    // p->draw();

    int choice;
    while(1)
    {
        scanf("%d", &choice);

        switch(choice)
        {
            case 1:
                ps = &c;
                ps->draw();
                break;
            case 2:
                ps = &r;
                ps->draw();
                break;
        }
    }
    
    return 0;
}

El método para declarar una función virtual virtual void func(); palabra clave declarativa

anular anular

sobrecarga Sobrecarga: mismo alcance, mismo nombre de función, lista de parámetros diferente

sombra: miembros con el mismo nombre que aparecen en clases padre e hijo

override: Ocurre en las clases padre e hijo, y la función en la clase padre tiene una función de declaración virtual

En la subclase, los mismos parámetros, el mismo nombre y la misma función de retorno constituyen una anulación

función virtual pura

Formato: sorteo de vacío virtual() = 0;

Una función virtual pura no tiene cuerpo de implementación y una clase que contiene una función virtual pura se denomina clase base abstracta.

No se pueden crear instancias de clases base abstractas

En Java, se llama interfaz y su función es proporcionar una interfaz para la familia.

Patrones de diseño

Los módulos de alto nivel no deberían depender de los módulos de bajo nivel, ambos deberían depender de sus abstracciones; las abstracciones no deberían depender de los detalles; los detalles deberían depender de las abstracciones

Lógica empresarial de alto nivel == capa de abstracción == lógica empresarial de bajo nivel

#include <iostream>

using namespace std;

class IReader
{
public:
    virtual void content();
};

class Story:public IReader
{
public:
    void content()
    {
        cout<<"story one"<<endl;
    }
};

class Newspaper:public IReader
{
public:
    void content()
    {
        cout<<"newspaper"<<endl;
    }
};

class Mother
{
public:
    void read_content(IReader * i)
    {
        i->content();
    }
};

int main()
{
    Mother mo;
    Story s;
    Newspaper ns;

    mo.read_content(&s);
    mo.read_content(&ns);

    return 0;
}

tabla de funciones virtuales

El polimorfismo de C++ se realiza a través de una tabla de funciones virtuales (Virtual Table), denominada V-Table.

Hay una tabla de direcciones de funciones virtuales en la tabla, que resuelve el problema de herencia y sobrescritura y garantiza que refleje verdaderamente la función real.

Esta tabla se asigna en la memoria de la instancia.

código estático

Base *b = nueva Derivada();

b->f();

Primero aclare el tipo de b; luego haga coincidir la entrada de la función virtual a través del puntero vptr y el desplazamiento de la tabla de funciones virtuales del puntero ; llame a la función virtual de acuerdo con la dirección de entrada

El polimorfismo permite la unión dinámica, pero sacrifica algo de espacio y eficiencia.

Información de tipo de tiempo de ejecución (RTTI)

identificación del tipo de tiempo de ejecución

typeiddynamic_cast solo se usa para la conversión de clases padre-hijo con funciones virtuales

Administrador *t =dynamic_cast<Administrador*>(emp[i]);

int main()
{
    B b;
    A * pa = &b;

    B * pb = dynamic_cast<B*>(pa);
    cout<<pb<<endl;  // 输出地址

    C * pc = dynamic_cast<C*>(pa);
    cout<<pc<<endl;  // 输出0

    return 0;
}

mecanografiado

#include <iostream>
#include <typeinfo>

using namespace std;
typedef void (*PF)(int);

int main()
{
    //检查类型信息
    cout<<typeid(int).name()<<endl;  // i
    cout<<typeid(char).name()<<endl;  // c
    cout<<typeid(double).name()<<endl;  // d
    cout<<typeid(float).name()<<endl;  // f
    cout<<typeid(long).name()<<endl;  // l

    cout<<typeid(PF).name()<<endl;  //PFviE

    return 0;
}

B、C 均继承A
D是单独的类

int main()
{
    B b;
    A * pa = &b;
    
    B * pb = static_cast<B*>(pa);  // 成功
    cout<<pb<<endl;

    C * pc = static_cast<C*>(pa);  // 成功  不安全
    cout<<pc<<endl;

    D * pd = static_cast<D*>(pa);  // 不成功
    cout<<pd<<endl;

    

    B * pb = reinterpret_cast<B*>(pa);  //  成功 不安全
    cout<<pb<<endl;

    C * pc = reinterpret_cast<C*>(pa);  //  成功 不安全
    cout<<pc<<endl;

    D * pd = reinterpret_cast<D*>(pa);  //  成功 不安全
    cout<<pd<<endl;

    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/jiangyangll/article/details/132344004
Recomendado
Clasificación