An abstract class

If you type the class keyword in c++, idea will automatically create a class like this:

class Base
{
private:
    /* data */
public:
    Base(/* args */);
    ~Base();
};

Base::Base(/* args */)
{
}

Base::~Base()
{
}
Copy the code

Above is a basic class, including private and public members, constructors, and destructors.

If we add a pure virtual function, the class is abstract:

class Base
{
    private:
        People *people;
    public:
        Base(){
            cout<<"create Base"<<endl;
        };
        ~Base(){
            cout << "deleted Base" << endl;
        };
        virtual void fun() = 0;
};
Copy the code

An error will be reported if we create a Base object directly, because Base is an abstract class and must be implemented by subclasses

We implement A subclass of A by inheritance:

class A:public Base { private: int a = 0; public: A(int i):Base(){ a = i; cout<<"create A"<<endl; }; ~A(){ cout << "deleted A" << endl; }; void fun(){ cout << "funA"<<endl; }};Copy the code

The constructors of subclasses need to inherit the constructors of the Base class and also need to implement pure virtual functions in Base

Using abstract classes with Pointers:

int main(){ A a(1); // The abstract class pointer must point to its implementation class object Base * Base; base = &a; base->fun(); // Or: Base *base2 = new A(123); base2->fun(); system("pause"); return 0; }Copy the code

Conclusion:

  • Pointers to abstract classes must point to their derived classes
  • A derived class becomes abstract if it does not implement pure virtual functions
  • Abstract classes can have constructors
  • Constructors cannot be virtual, destructors can be virtual (why, explained below)

Multiple inheritance

Above we create A class A inheritance class Base, which is A single inheritance, we create A class B inheritance from class A:

Class A:public Base{} Class B:public A{}Copy the code

So is class B multiple inheritance? No, but to achieve the effect of multiple inheritance

class C{}

class B:public C,public A{}
Copy the code

So B is multiple inheritance, so B has parts A and C in it.

Note that if the parent class has the same base class, this is not recommended:

Class A:public Base{} class C:public Base{} class B:public A,C{}Copy the code

A and C inherit from the Base class, and B inherit from A and C. In order to solve the above problems, the concept of virtual inheritance is proposed in C ++ as follows:

class A{}; class B : virtual public A { }; Class C: virtual public A {}; Class D: public B, public C {};Copy the code

The effect of virtual inheritance is to allow declared classes to share the base class, if there is only one base object no matter how many times it occurs in subsequent inheritance.

We created the following code from the above example:

class A:virtual public Base { private: int a = 0; public: A(int i):Base(){ a = i; cout<<"create A"<<endl; }; ~A(){ cout << "deleted A" << endl; }; void fun(){ cout << "funA"<<endl; }}; class B:public A,virtual public Base { private: int b = 0; public: B(int i,int j):A(j){ cout<<"create B"<<endl; b = i; }; ~B(){ cout << "deleted B" << endl; }; void fun(){ cout << "funB"<<endl; }};Copy the code

Class B resolves the Base class inheritance problem by using:

Base *base2 = new B(123,322);
base2->fun();

Copy the code

Virtual

polymorphism

Abstraction, multiple inheritance, all of this is to achieve polymorphism, what is polymorphism? Classes with the same name can instantiate different objects with different types to achieve different effects. While polymorphism is indeterminate at compile time, only run-time can determine the total type, so we divide it into static compilation and dynamic compilation:

Static binding, also known as static binding, refers to the specific function corresponding to it is determined according to the information provided by the calling function during compilation, that is, the calling function name and the specific function are bound together at compilation time.

Dynamic binding, also known as dynamic binding, means that the specific function corresponding to the function call cannot be determined during the compilation of the program, but can only be determined during the running of the program, that is, the calling function name and the specific function are bound together when the program is running.

Virtual functions

Virtual is used to declare virtual functions, but why do we need virtual functions?

Virtual is essentially used to tell the system that this function is dynamically organized. Virtual functions are stored in the virtual function table, called vtable, after the function is run

1. Access a member defined in a derived class through a base class pointer
Base *base = new A();
base->fun();
Copy the code

Base accesses the fun method of A class object. That is, base creates objects that point to its derived objects, and accesses only the methods that the derived classes inherit from

2. When a base class pointer points to a derived class, the virtual function accessed is the version of the derived class.

Examples are as follows:

#include <iostream> using namespace std; class Base { private: int i = 0; public: Base(){ }; virtual ~Base(){ cout<<"deleted Base"<<endl; }; virtual void fun1() = 0; virtual void fun2(){ cout <<"Base::fun2()"<<endl; }; }; class A:virtual public Base { private: int j = 0; public: A():Base(){ }; ~A(){ cout<<"deleted A"<<endl; }; / / Base: : fun2 overloaded function / / void fun2 () {/ / cout < < "A: : fun2 ()" < < endl; / /}; //Base::fun2 virtual void fun2(){cout<<"A::fun2()"<<endl; }; }; int main(){ Base *base = new A(); base->fun1(); base->fun2(); delete base; return 0; }Copy the code

Output result:

A::fun1()
A::fun2()
deleted A
deleted Base
Copy the code

We see the difference between fun2 being a virtual function and an overloaded function, and whether it is exactly the same as a virtual function in the base class.

A virtual function can be characterized only if the virtual function of a derived object is accessed through Pointers and references to the base object.

3. The default parameters of virtual functions are based on the base class

Examples are as follows:

#include <iostream> using namespace std; class Base { public: virtual void fun ( int x = 10 ) { cout << "Base::fun(), x = " << x << endl; }}; class Derived : public Base { public: virtual void fun ( int x=20 ) { cout << "Derived::fun(), x = " << x << endl; }}; int main() { Derived d1; Base *bp = &d1; bp->fun(); // 10 return 0; }Copy the code

Although virtual functions are dynamically marshalled, the default parameters are statically marshalled, so the default parameters are the pointer types themselves.

5. What function cannot be virtual?

Constructor, static function

  • Static functions do not belong to any class, are statically bound, and cannot be const, volatile, or otherwise.
  • The vtable is a table of virtual functions. Although the vtable is statically linked, it is determined by the compiler. However, the VPTR pointer to the vtable is created during the run-time instantiation, and the first constructor is instantiated, so the two will conflict.

In addition: It is not recommended that private and inline functions be declared virtual (yes, but not necessary)

6. What functions can be virtual?

In addition to the commonly defined virtual functions, destructors can also be virtual, and the destructors of general abstract classes are virtual.

Suppose you destroy a derived object using DELETE and a base pointer to the derived class. If the base destructor is not virtual, just like a normal member function, the delete function calls the base destructor. When a derived object is called through a reference or pointer to a base object, the object is not completely destructed!