C ++ polymorphism associated

What is polymorphism? What is the realization of the principle of virtual functions?

Polymorphism Polymorphism is divided into static and dynamic polymorphism

  • Static Polymorphism: at compile time, the main function overloading, operator overloading
  • Dynamic polymorphism: occur at run time, the main achievement in the form of a virtual function
    polymorphism can be summarized as "one interface, multiple methods", the program decides at runtime function calls, polymorphism is the core oop programming, polymorphism C ++ virtual functions implemented by, defined in the base class virtual function, and may allow the subclass inherits redefine the function implemented, which is covered. Polymorphism purpose is to interface reuse. In other words, no matter which class is passed over an object, the function can be called to implement the method for each object through the interface.
    The most common use is to declare a pointer or reference to the base class, then the object is a pointer or reference to a derived class of binding, calls the corresponding virtual functions may be implemented in different ways depending on the derived class directed.

The principle of virtual functions: when a virtual function in the class is defined, then the storage location of this class will be instantiated object in a plurality vfptr pointer that points to a virtual function table, the virtual function table that is stored in the virtual function entry address


The constructor can be set to the virtual function? why?

Constructor can not be set to the virtual function is a virtual function is implemented in C ++ OOP programming set of polymorphism, and dynamic activation conditions polymorphisms:

  • It is defined in the base class virtual function, derived classes while covering the function definition of the function;
  • Create a derived class object
  • Define a pointer or reference to the base class, and bound to its derived class objects; defined by the base class has a pointer or reference to the corresponding virtual function call

== dynamic polymorphism may know by the above activation conditions, to use the virtual rational function, you must first create an object of a derived class, the derived class object is created in the process will call the constructor of its base class, and if the base class constructor is virtual function, but this time they did not create a derived class object, caught in a conflict situation, so the constructor can not be set as virtual functions, but also not a matter of any significance ==


Under what circumstances the destructor to be provided to the virtual function? why?

When the base class data members application heap space, which also defines the base class virtual function of the space and the destructor for the destruction. If the derived class has a base class, the derived class also applied for a heap. Then if we derive a new class space, the new expression returns a pointer to a derived class is assigned to a base class pointer. If we use delete to free expression derived class space just to apply, then we will call the destructor of the base class does not call the destructor of the derived class, as it has been derived class pointer is assigned to a base class pointer . At this point we should set the destructor virtual function, while calling the destructor of the derived class, but also will call the base class destructor, then the resources of all applications have been released. code show as below:

#include <string.h>

#include <iostream>

using std::cout;
using std::endl;

class Base
{
public:
    Base(const char * base)
    : _base(new char[strlen(base) + 1]())
    {
        strcpy(_base, base);
        cout << "Base(const char * base)" << endl;
    }

    virtual void print(void) const
    {
        cout << "base = " << _base << endl;
    }

    ~Base()
    {
        if (_base)
            delete [] _base;
        cout << "~Base()" << endl;
    }

private:
    char * _base;
};

class Derived
: public Base
{
public:
    Derived(const char * base, const char * derived)
    : Base(base)
    , _derived(new char[strlen(base) + 1]())
    {
        strcpy(_derived, derived);
        cout << "Derived(const char * base, const char * derived)" << endl;
    }
    
    void print(void) const 
    {
        cout << "derived = " << _derived << endl;
    }

    ~Derived()
    {
        if (_derived)
            delete [] _derived;
        cout << "~Derived()" << endl;
    }
private:
    char * _derived;

};

int main(void)
{
    Base * base = new Derived("hello", "world");
    base->print();

    delete base;

    return 0;
}

operation result

Base(const char * base)
Derived(const char * base, const char * derived)
derived = world
~Base()

Analysis: for the virtual function call is no longer analysis here, the derived class is the base class virtual function to the covering, then calls the base class object from the base class virtual function, will be derived class virtual function call. Here Analysis destructor, by running results, when delete base, the base class destructor is invoked, but the derived class destructor is not invoked, i.e., the stack base class resource request has been release, and the derived class resources have not been released, it's not the result we want, above reasons have been analyzed. To solve this problem, you should think of, when you call the derived destructor, the destructor of the base class will be called automatically, we can try to call the derived class destructor, then how to call the derived class destructor of it ? Herein may be utilized to cover the characteristics of virtual functions, we base class destructor to virtual, this case will be called a derived class destructor during delete base, to achieve our purpose, code changes as follows:

virtual
    ~Base()
    {
        if (_base)
            delete [] _base;
        cout << "~Base()" << endl;
    }

operation result:

Base(const char * base)
Derived(const char * base, const char * derived)
derived = world
~Derived()
~Base()

When the base class destructor to virtual function, derived classes destructor will automatically become the virtual destructor, even without adding the virtual keyword, if the destructor to be called next, the virtual function call will go mechanism


The case when the virtual function call inside the common base class member function

#include <iostream>

using std::cout;
using std::endl;

class Base 
{
public:
    Base() = default;

    Base(int base_val)
    : _base_val(base_val)
    {
        cout << "Base(int base_val)" << endl;
    }

    void func1(void)
    {
        //this->display();
        display();
    }

    void func2(void)
    {
        Base::display();
    }

    virtual void display(void) const
    {
        cout << "base_val = " << _base_val << endl;
    }

private:
    int _base_val;

};

class Derived
: public Base
{
public:
    Derived(int base_val, int derived_val)
    : Base(base_val)
    , _derived_val(derived_val)
    {
        cout << "Derived(int base_val, int derived_val)" << endl;
    }

    void display(void) const
    {
        cout << "derived_val = " << _derived_val << endl;
    }
private:
    int _derived_val;
};

int main(void)
{
    Base base(12);
    base.func1();

    Derived derived(34, 56);
    derived.func1();

    cout << "-----------" << endl;
    base.func2();
    derived.func2();

    return 0;
}

operation result:

Base(int base_val)
base_val = 12
Base(int base_val)
Derived(int base_val, int derived_val)
derived_val = 56
-----------
base_val = 12 base_val = 34

Analysis: apparent from the above code, the display () virtual function for function definition, while the base class function func1 and func2 to access the virtual function in two ways; Base base (12); base.func1 (); for this code is well understood, it is essential to create an object, and then access the member object, just visit the virtual function of the object in the members, but because there is no inheritance, and so there is no difference between an ordinary visit;

Derived derived(34, 56);
derived.func1();

For this code, since the Base Derived classes inherit from classes in the base class inherits the func1, func2, and virtual functions, since the class Derived redefine the virtual function, the function of the same name at this time subclasses override base class virtual function, it is a subclass of time func1 calls the redefined virtual function;

base.func2();
derived.func2();

By running the above code results, although the function func2 derived object called, but the scope of the internal function by the operator calls virtual function, then the call will directly call the base class virtual function, it does not invoke the derived class virtual function


The case when the virtual function call within the constructor and destructor of the base class

#include <iostream>

using std::cout;
using std::endl;

class Grandpa 
{
public:
    Grandpa(int grandpa_val)
    : _grandpa_val(grandpa_val)
    {
        cout << "Grandpa(int grandpa_val)" << endl;
    }

    virtual
    void func1(void)
    {
        cout << "Grandpa: func1()" << endl;
    }

    virtual
    void func2(void)
    {
        cout << "Grandpa: func2()" << endl;
    }

    ~Grandpa()
    {
        cout << "~Grandpa()" << endl;
    }
private:
    int _grandpa_val;

};

class Son
: public Grandpa
{
public:
    Son(int grandpa_val, int son_val)
    : Grandpa(grandpa_val)
    , _son_val(son_val)
    {
        cout << "Son(int grandpa_val, int son_val)" << endl;
        func1();
    }

#if 1
    void func1(void)
    {
        cout << "Son: func1()" << endl;
    }

    void func2(void)
    {
        cout << "Son: func2()" << endl;
    }

#endif 

    ~Son()
    {
        cout << "~Son()" << endl;
        func2();
    }
private:
    int _son_val;
};

class Grandson
: public Son
{
public:
    Grandson(int grandpa_val, int son_val, int grandson_val)
    : Son(grandpa_val, son_val)
    , _grandson_val(grandpa_val)
    {
        cout << "Grandson(int grandpa_val, int son_val, int grandson_val)" << endl;
    }

    void func1(void)
    {
        cout << "Grandson: func1()" << endl;
    }

    void func2(void)
    {
        cout << "Grandson: func2()" << endl;
    }

    ~Grandson()
    {
        cout << "~Grandson()" << endl;
    }

private:
    int _grandson_val;
};

int main(void)
{
    Grandson test(1, 2, 3);
    //cout << "-------------/\n";
    Grandpa  & tt = test;
    cout << "-------------/\n";
    tt.func1();
    return 0;
}

operation result

Grandpa(int grandpa_val)
Son(int grandpa_val, int son_val)
Son: func1()
Grandson(int grandpa_val, int son_val, int grandson_val)
-------------/
Grandson: func1()
~Grandson()
~Son()
Son: func2()
~Grandpa()

Known by the code and operating results, when we call the constructor or destructor internal virtual functions, although the surface and dynamic binding distinction did not say, however, these two functions within the virtual function call, the call in fact essentially is itself a function of the class (not virtual), or that there is no call from the virtual function mechanism, but the mechanism in accordance with the ordinary call function (static binding)


Presence verification vtable

We know that if a base class virtual function is defined, while covering the derived class virtual function, then the derived storage instance derived class object class which will be created when a plurality of points to virtual function table pointer, enabling performance of the dynamic nature of the polymorphism, the presence here of the virtual function table for verification, as follows:

#include <iostream>

using std::cout;
using std::endl;

class Base
{
public:
    Base(long base_val)
    : _base_val(base_val)
    {
        cout << "Base(int base_val)" << endl;
    }

    virtual 
    void func1(void)    {   cout << "Base::func1()" << endl;    }

    virtual 
    void func2(void)    {   cout << "Base::func2()" << endl;    }

    virtual 
    void func3(void)    {   cout << "Base::func3()" << endl;    }

private:
    long _base_val;

};

class Derived
: public Base
{
public:
    Derived(long base_val, long derived_val)
    : Base(base_val)
    , _derived_val(derived_val)
    {
        cout << "Derived(long base_val, long derived_val)" << endl;
    }

    virtual 
    void func1(void)    {   cout << "Derived::func1()" << endl;    }

    virtual 
    void func2(void)    {   cout << "Derived::func2()" << endl;    }

    virtual 
    void func3(void)    {   cout << "Derived::func3()" << endl;    }

private:
    long _derived_val;
    
};

int main(void)
{
    Base base(10);
    cout << "sizeof(Base) = " << sizeof(Base) << endl;  

    long * p = (long *)&base;
    cout << p[0] << endl;
    cout << p[1] << endl; 

    typedef void (*Function)(void);

    long * p2 = (long *)p[0];
    Function f = (Function)p2[0];
    //Function f = (Function)p[0][0];
    f();

    f = (Function)p2[1];
    f();

    f = (Function)p2[2];
    f();

    return 0;
}

operation result

Base(int base_val)
sizeof(Base) = 16
94272637283664
10
Base::func1()
Base::func2()
Base::func3()

Compilation and runtime are gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1 ~ 18.04.1), so the system is 64 bits, so the size of a pointer is 8 bytes (64 bits), so in order to facilitate verification , where long data type to store. We know that the size of the object in the base of the stack is 16 bytes, 8 bytes long type of data, 8 bytes and the pointer is vfptr pointer to the virtual function table, this is false verification Are there really function table. An object base fetch address, cast to long type, see p [1] data that we start initialization values ​​assigned to base objects, p [0] is a pointer to the virtual function table, because the size of a pointer is 8 bytes, so we once again to p [0] long * cast type, we can look out from the program, p [0] There are three pointers, that is, the data p2, p2 since the data is 8-byte pointer, but the compiler does not recognize the address data, the data so we cast a function pointer, so that you can call the virtual function. A virtual function table to verify the existence oh


What is a pure virtual function? What is an abstract class? What is the role of abstract class?

  • Refers to a pure virtual function in the base class virtual function is not defined, but the pure virtual functions declared when added behind = 0; can, then the base class virtual function is a pure virtual function
  • If a pure virtual function is defined in the base class, the base class is the abstract base class, abstract base class only outwardly interface and not instantiate the object, when the group derived class objects can be instantiated, but the premise is that these the derived class defines a function covering these pure virtual function, here we glance through the abstract base class is only responsible for providing the interface definition, is not responsible for implementation of the interface, implementation of the interface is done by the base class of the derived class. code show as below:
#include <math.h>

#include <iostream>

using std::cout;
using std::endl;

class Figure            //定义一个抽象基类
{
public: 
    virtual void display(void) const = 0;   //定义纯虚函数
    virtual double area(void) const = 0;
};

void display(Figure & figure)
{
    figure.display(); 
    cout << ", the area is " << figure.area() << endl;
}

class Circle
: public Figure
{
public:
    Circle(double radius)
    : _radius(radius)
    {}

    void display(void) const
    {
        cout << "I am Circle";
    }

    double area(void) const
    {
        return 3.14 * _radius * _radius;
    }

private:
    double _radius;
};

class Rectangle
: public Figure
{
public:
    Rectangle(double length, double width)
    : _length(length)
    , _width(width)
    {}

    void display(void) const
    {
        cout << "I am Rectangle";
    }

    double area(void) const
    {
        return _length * _width;
    }

private:
    double _length;
    double _width;
};

class Triangle
: public Figure
{
public:
    Triangle(double a, double b, double c)
    : _a(a)
    , _b(b)
    , _c(c)
    {}

    void display(void) const
    {
        cout << "I am Triangle";
    }

    double area(void) const
    {
        double p = (_a + _b + _c)/2;
        return sqrt(p * (p - _a) * (p - _b) * (p - _c));
    }

private:
    double _a;
    double _b;
    double _c;
};

int main(void)
{
    Circle circle(10);
    Rectangle rec(10, 12);
    Triangle triangle(3, 4, 5);

    display(circle);
    display(rec);
    display(triangle);


    return 0;
}

operation result:

I am Circle, the area is 314
I am Rectangle, the area is 120
I am Triangle, the area is 6

Analysis: From the above code can be known, as Figure abstract base class that defines various interfaces only outwardly provided, is achieved by a derived class of the base class to complete the main function we can see, with a call function, but the result was not the same. This principle is the abstract base class follow: Close modification (without modifying the original code), open to the extension.
Another: abstract base class for this to be noted that, as long as the base class with a pure virtual function is defined, it must be given to the derived class for all pure virtual functions implemented in the base class, as long as there is not a pure virtual function to achieve , the derived class can not create object.
As defined above is a pure virtual function to achieve an abstract class, an abstract, there is another class, the base class constructor is set to protected, this time the base class is not instantiated object configured to call the base class function, through which base class to subclass, the subclass is instantiated to call the members of the base class can be accessed through the object, as follows:

#include <iostream>

using std::cout;
using std::endl;

class Base
{
public:
    virtual void print(void)
    {
        cout << "I am Base_class" << endl;
        cout << "base_val = " << _base_val << endl;
    }

protected:              //把基类的构造函数定义为protected性质,这时外部非派生类将不能对该类进行实例化,只能通过该类的派生来调用该基类的构造函数
    Base(int base_val)
    : _base_val(base_val)
    {
        
        cout << "Base(int base_val)" << endl;
    }

private:
    int _base_val;
};

class Inherit_cls
: public Base
{
public:
    Inherit_cls(int base, int inherit_val)      //通过派生类中的构造函数来调用基类中的构造函数
    : Base(base)
    , _inherit_val(inherit_val)
    {
        cout << "Inherit_cls(int base, int inherit_val) " << endl;
    }

    void print(void)
    {
        cout << "I am Inherit_cls" << endl;
        cout << "inherit_val = " << _inherit_val << endl;
    }

private:
    int _inherit_val;

};

int main(void)
{
    Inherit_cls test(12, 34);
    Base & base = test;
    base.print();

    return 0;
}

Analysis: The above code is dynamic polymorphism C ++ language, but the constructor for the base class is provided protected, this case is not to create a base class object by the base class, the base class can be created only by the derived class objects, before such an abstraction in terms of one kind of function as compared to a much weaker for the abstract class, should be used to achieve a pure virtual function.

What is overloaded? What is hidden? What is covered? The difference between them is that before?

  • Overload: overloads in the same class, and may be ordinary functions, so long as the function name, but the same number of function parameters, parameter types, the return values ​​are different, can be achieved reload
  • Hide: Hide the same name refers to a function of the parent-child relationship in the class inheritance, if there is a function function in the base class, the subclass also has a function function, this time will be hidden in the base class function function, you want to call the base function function class, only to add a scope qualifier
  • Cover: refers to the virtual function, if the base class defines a virtual function, while the base class is a derived class also defines the same name in a base class, with the return value, with the function parameter list (there may be no virtual modification), in this case the derived class object instantiated, then the derived class virtual function will overwrite inherited from the base class virtual function over

Multiple inheritance, virtual functions circumstances

#include <iostream>

using std::cout;
using std::endl;

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

    virtual 
    void g(void)    {   cout << "A::g()" << endl;   }

    virtual 
    void h(void)    {   cout << "A::h()" << endl;   }
};

class B
{
public: 
    virtual
    void f(void)    {   cout << "B::f()" << endl;   }

    virtual 
    void g(void)    {   cout << "B::g()" << endl;   }
 
    void h(void)    {   cout << "B::h()" << endl;   }

    void j(void)    {   cout << "B::j()" << endl;   }
};

class C 
: public A
, public B
{
public:
    virtual
    void f(void)    {   cout << "C::f()" << endl;   }

    void h(void)    {   cout << "C::g()" << endl;   }

    void j(void)    {   cout << "C::j()" << endl;   }
};


int main(void)
{
    C c;
    cout << "sizeof(A) = " << sizeof(A) << endl;

    A & a = c;
    a.f();
    a.g();
    a.h();
    cout << "-----------------" << endl;

    B & b = c;
    b.f();
    b.g();
    b.h();
    b.j();

    c.f();
    //c.g();
    c.h();
    c.j();

    return 0;
}

operation result

sizeof(A) = 8
C::f()
A::g()
C::g()
/-----------------
C::f()
B::g()
B::h()
B::j()
/---------------
C::f()
C::g()
C::j()

Apparent from the above code, where multiple inheritance virtual function refers to C multiple inheritance from A, B two classes; C at the same time also inherits A, virtual function table B, C are defined in the class if the cover A, B of virtual function, then the vtable will change the virtual function, the original base class virtual function coverage derived class virtual function, thus showing polymorphism dynamic properties. For such cases, the various types of virtual functions inheritance drawn, at a glance.

Guess you like

Origin www.cnblogs.com/dengxinlong/p/11299115.html