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