Basic concepts of polymorphism
Polymorphism is one of the three object-oriented features of C++
Polymorphism falls into two categories:
- Static polymorphism: function overloading and operator overloading are statically polymorphic and reuse function names
- Dynamic polymorphism: Derived classes and virtual functions implement runtime polymorphism
The difference between static polymorphism and dynamic polymorphism:
- Statically polymorphic function address early binding – Function address determination at compile stage (statically linked)
- Function address of Dynamic polymorphism late binding – Run-time determination of function address (dynamic linking)
Dynamic polymorphism meets the following conditions:
- Have a hereditary relationship
- Subclasses override virtual functions of their parent classes. Subclasses may omit the keyword virtual
Use of dynamic polymorphism:
A pointer or reference to a parent class points to a subclass object
#include<iostream> using namespace std; Class Animal {public: virtual void Speak(){cout<<" "<<endl; }}; Class Cat:public Animal {public: void Speak(){cout<<" Cat meow "<<endl; }}; Class Dog:public Animal {public: void Speak(){cout<<" Dog is barking "<<endl; }}; void DoSeak(Animal & animal){ animal.Speak(); } void test01(){ Cat cat; DoSeak(cat); Dog dog; DoSeak(dog); } int main() { test01(); return 0; }Copy the code
2. Benefits of polymorphism
Benefits of polymorphism:
- Clear organizational structure
- readable
- For the early and late expansion and maintenance of high
Pure virtual functions and abstract classes
In polymorphism, the implementation of virtual functions in the parent class is usually meaningless, and is mainly to call the content overridden by the subclass
Therefore, virtual functions can be changed to pure virtual functions with the following syntax:
Virtual return value type function name (argument list)=0;Copy the code
When a class has a pure virtual function, it is also called an abstract class
Abstract class features:
- Object cannot be instantiated
- A subclass must override all pure virtual functions in its abstract parent class, otherwise it also belongs to the abstract class
The following is an example of making drinks:
#include<iostream> using namespace std; class AbstractDrinking { public: virtual void Boil()=0; virtual void Brew()=0; virtual void PourInCup()=0; virtual void Putsth()=0; void makedrink(){ Boil(); Brew(); PourInCup(); Putsth(); }}; Class Coffee:public AbstractDrinking {public: void Boil(){cout<<" Boil "<<endl; } void Brew(){cout<<" Brew "<<endl; } void PourInCup(){cout<<" pour into the coffee cup "<<endl; } void Putsth(){cout<<" add sugar and milk "<<endl; }}; Class Tea:public AbstractDrinking {public: void Boil(){cout<<" Boil "<<endl; } void Brew(){cout<<" Brew "<<endl; } void PourInCup(){cout<<" pour into the cup "<<endl; } void Putsth(){cout<<" "<<endl; }}; void doWork(AbstractDrinking* a){ a->makedrink(); delete a; } void test01(){ doWork(new Coffee); cout<<"--------------"<<endl; doWork(new Tea); } int main() { test01(); return 0; }Copy the code
Virtual and pure virtual destructions
When polymorphism is used, if a property in a subclass is opened to the heap, then the parent class pointer cannot call the subclass’s destructor code when it is released, resulting in a memory leak
Workaround: Change the destructor in the parent class to virtual or pure virtual
The commonality of virtual and pure virtual destructions:
- Can resolve the parent class pointer to release the subclass object
- They all need to be implemented in a specific way
The difference between virtual and pure virtual destructions:
- If it is pure virtual destructor, the class is abstract and cannot instantiate the object
Virtual destructor syntax:
Virtual ~ class name (){... }Copy the code
Pure virtual destructor syntax:
Virtual ~ class name ()=0;Copy the code
Class name ::~ Class name (){... }Copy the code
The following is an example constructed with virtual destructor:
#include<iostream> #include<string> using namespace std; Class Animal {public: Animal(){cout<<"Animal constructor "<<endl; } // virtual ~Animal(){cout<<"Animal virtual destructor call "<<endl; } virtual void Speak()=0; // pure virtual function}; class Cat:public Animal { public: string* m_Name; Void Speak(){cout<<*m_Name<<" meow "<<endl; } Cat(string name){ m_Name=new string(name); Cout <<"Cat constructor call "<<endl; } ~Cat(){cout<<"Cat destructor call "<<endl; if(m_Name! =nullptr){ delete m_Name; m_Name=nullptr; }}}; void test01(){ Animal* animal=new Cat("Tom"); animal->Speak(); delete animal; } int main() { test01(); return 0; }Copy the code
If it is pure virtual destructor, the core code is as follows:
Class Animal {public: Animal(){cout<<"Animal constructor "<<endl; } // Virtual ~Animal()=0; virtual void Speak()=0; // pure virtual function}; Animal::~Animal() {cout<<"Animal pure virtual destructor "<<endl; }Copy the code
5 Comprehensive Cases
#include<iostream> using namespace std; Class CPU//CPU abstract class {public: virtual void Calculate ()=0; }; Class VidoeCard {public: virtual void display()=0; }; Class Memory// Store abstract class {public: virtual void storage()=0; }; Public: Computer(CPU* CPU,VidoeCard* vc,Memory* mem){m_CPU = CPU; m_vc=vc; m_mem=mem; } ~Computer(){ if(m_cpu! =nullptr){ delete m_cpu; m_cpu=nullptr; } if(m_vc! =nullptr){ delete m_vc; m_vc=nullptr; } if(m_mem! =nullptr){ delete m_mem; m_mem=nullptr; } } void Work(){ m_cpu->calculate(); m_vc->display(); m_mem->storage(); } private: CPU* m_cpu; VidoeCard* m_vc; Memory* m_mem; }; Class IntelCPU:public void calculate(){cout<<" Calculate "<<endl; }}; Class IntelVideoCard:public VidoeCard {void display(){cout<<"Intel VideoCard starts showing "<<endl; }}; Class IntelMemory:public Memory {void storage(){cout<<"Intel Memory started "<<endl; }}; Class LenoveCPU:public CPU {void calculate(){cout<<" Calculate "<<endl; }}; Class LenoveVideoCard:public VidoeCard {void display(){cout<<"Lenove VideoCard starts showing "<<endl; }}; Class LenoveMemory:public Memory {void storage(){cout<<"Lenove Memory started to store "<<endl; }}; Void test01() {// First CPU* Intelcpu=new Intelcpu; VidoeCard* IntelCard=new IntelVideoCard; Memory* Intelmem=new IntelMemory; Cout <<" The first computer started working "<<endl; Computer* computer1=new Computer(Intelcpu,IntelCard,Intelmem); computer1->Work(); delete computer1; cout<<"-------------------------"<<endl; Cout <<" The second computer is working "<<endl; Computer* computer2=new Computer(new LenoveCPU,new LenoveVideoCard,new LenoveMemory); computer2->Work(); delete computer2; cout<<"-------------------------"<<endl; Cout <<" The third computer is working "<<endl; Computer* computer3=new Computer(new LenoveCPU,new IntelVideoCard,new IntelMemory); computer3->Work(); delete computer3; } int main() { test01(); return 0; }Copy the code
6 Reference Links
www.bilibili.com/video/BV1et…