C++(7) polymorphism

polymorphism polymorphism 

1. There are virtual functions in the parent class

2. Override the virtual function of the parent class in the subclass

3. The address of the subclass object is assigned to the pointer of the parent class, and the virtual function is used through the pointer

#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;
}

Assignment compatibility only occurs in public derived parent-child relationships

Subclass objects are assigned to objects of the parent class

References assigned by subclass objects to parent classes

The address of the subclass object is assigned to the pointer of the parent class 

#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;
}

Static polymorphism: determined during compilation

Dynamic polymorphism: determined at runtime

polymorphism

1. There is a virtual function in the parent class, and the virtual function virtual is declared

2. The virtual function of the parent class is overridden in the subclass

3. Assign the address of the subclass object to the pointer of the parent class, and call the virtual function

#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;
}

The method of declaring a virtual function virtual void func(); declarative keyword

override override

overload Overloading: same scope, same function name, different parameter list

shadow : Members with the same name that occur in parent and child classes

override : Occurs in the parent and child classes, and the function in the parent class has a virtual declaration function

In the subclass, the same parameters, the same name, and the same return function constitute an override

pure virtual function

Format: virtual void draw() = 0;

A pure virtual function has no implementation body, and a class containing a pure virtual function is called an abstract base class

Abstract base classes cannot be instantiated

In java, it is called the interface interface, and its function is to provide an interface for the family.

Design Patterns

High-level modules should not depend on low-level modules, both should depend on their abstractions; abstractions should not depend on details; details should depend on abstractions

High-level business logic == abstraction layer == low-level business logic

#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;
}

virtual function table

The polymorphism of C++ is realized through a virtual function table (Virtual Table), referred to as V-Table.

There is an address table of virtual functions in the table, which solves the problem of inheritance and overwriting, and ensures that it truly reflects the actual function

This table is allocated in the memory of the instance

static code

Base *b = new Derive();

b->f();

First clarify the type of b; then match the entry of the virtual function through the pointer vptr and offset of the pointer virtual function table ; call the virtual function according to the entry address

Polymorphism enables dynamic binding, but sacrifices some space and efficiency.

Runtime Type Information (RTTI)

run time type identification

typeid dynamic_cast is only used for parent-child class conversion with virtual functions

Manager *t = dynamic_cast<Manager*>(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;
}

typeid

#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;
}

Guess you like

Origin blog.csdn.net/jiangyangll/article/details/132344004