当前位置:网站首页>Polymorphism in detail (simple implementation to buy tickets system simulation, covering/weight definition, principle of polymorphism, virtual table)
Polymorphism in detail (simple implementation to buy tickets system simulation, covering/weight definition, principle of polymorphism, virtual table)
2022-08-03 10:50:00 【Han Xuanzi】
目录
1. 多态的概念
多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态,比如我们买火车票,Students and soldiers to buy tickets and adult ticket price is not the same as this is a polymorphic
2.Buy a ticket system simulation to realize
Know about the cover before implementation,// 虚函数 + 函数名/参数/返回值 相同等于 重写或者覆盖
class Person {
public:
// 虚函数
virtual void BuyTicket() {
cout << "Person:买票-全价 100¥" << endl; }
protected:
};
class Student : public Person {
public:
// 虚函数 + 函数名/参数/返回值 -》 重写/覆盖
virtual void BuyTicket() {
cout << " Student:买票-半价 50 ¥" << endl; }
};
class Soldier : public Person {
public:
// 虚函数 + 函数名/参数/返回值 -》 重写/覆盖
virtual void BuyTicket() {
cout << " Soldier:Priority set aside to buy tickets-88折 88 ¥" << endl; }
};
void Pay(Person* ptr)
{
ptr->BuyTicket();
}
int main()
{
Person p;
Student s;
Soldier st;
int option = 0;
cout << "=======================================" << endl;
do
{
cout << "请选择身份:";
cout << "1、普通人 2、学生 3、军人" << endl;
cin >> option;
switch (option)
{
case 1:
{
p.BuyTicket();
break;
}
case 2:
{
s.BuyTicket();
break;
}
case 3:
{
st.BuyTicket();
break;
}
default:
cout << "输入错误,请重新输入" << endl;
break;
}
cout << "=======================================" << endl;
} while (option != -1);
return 0;
}
运行结果
But this didn't the system,就是名字,Id like all have no
Before writing know polymorphic
Polymorphism two requirements:
1、A subclass of virtual function to rewrite the superclass virtual function (重写:三同(函数名/参数/返回值)+虚函数)
2、A parent class pointer or reference to call virtual functions.
#include<iostream>
using namespace std;
class Person
{
public:
Person(const char* name)
:_name(name)
{
}
// 虚函数
virtual void BuyTicket() {
cout << _name << "Person:买票-全价 100¥" << endl; }
protected:
string _name;
};
class Student : public Person {
public:
Student(const char* name)
:Person(name)
{
}
// 虚函数 + 函数名/参数/返回值 -》 重写/覆盖
virtual void BuyTicket() {
cout << _name << " Student:买票-半价 50 ¥" << endl; }
};
class Soldier : public Person {
public:
Soldier(const char* name)
:Person(name)
{
}
// 虚函数 + 函数名/参数/返回值 -》 重写/覆盖
virtual void BuyTicket() {
cout << _name << " Soldier:Priority set aside to buy tickets-88折 88 ¥" << endl; }
};
void Pay(Person& ptr)
{
ptr.BuyTicket();
}
int main()
{
int option = 0;
cout << "=======================================" << endl;
do
{
cout << "请选择身份:";
cout << "1、普通人 2、学生 3、军人" << endl;
cin >> option;
cout << "请输入身份" << endl;
string name;
cin >> name;
switch (option)
{
case 1:
{
Person p(name.c_str());
Pay(p);
break;
}
case 2:
{
Student s(name.c_str());
Pay(s);
break;
}
case 3:
{
Soldier sr(name.c_str());
Pay(sr);
break;
}
default:
cout << "输入错误,请重新输入" << endl;
break;
}
cout << "=======================================" << endl;
} while (option != -1);
return 0;
}
运行结果
As for can not meet the needs of polymorphism and virtual functions error case I am not going to,You can change yourself down,比如把pay的person*去掉,或者改成student,Or to change the definition of a virtual function,改下参数,See he is not a virtual function,Although I talked about the above requirement,Does not meet the conditions, it is not virtual function,But I think you can try yourself,Take a look at how he error,After seeing this error results,Know how to solve right away
But the virtual function to rewrite one exception to the return value requirement:协变,Parent-child relationships Pointers and references
class A{
};
class B : public A {
};
// Virtual functions to rewrite one exception to the return value requirement:协变,Parent-child relationships Pointers and references
class Person {
public:
virtual A* f() {
cout << "virtual A* Person::f()" << endl;
return nullptr;
}
};
class Student : public Person {
public:
// Subclasses virtual function didn't writevirtual,fStill the virtual function,Because the first interface inherits the parent class functions
// Rewrite the parent virtual function to achieve
// ps:When we write their own subclass virtual function also writevirtual
// B& f() {
virtual B* f() {
cout << "virtual B* Student::f()" << endl;
return nullptr;
}
};
int main()
{
Person p;
Student s;
Person* ptr = &p;
ptr->f();
ptr = &s;
ptr->f();
return 0;
}
运行结果
We do understand the virtual function under the topic
The above question and the answer isb,为什么?
首先先到p->test()明明是BWhy can subclass call the parent classA的test,Because of the subclass inherits the parent class to inherittest,But he inheritedtest里面的this是A*We need to address the past,It involves the transformation of the parents and children,而这里test里面this指针是B的指针,And it is just in accordance with the two conditions of the polymorphic,所以调用B的func,Could someone tell he didn'tvirtual啊,But we spoke above a subclass inherits parent will give inherited its virtual function,Is also the default inherited the parent class,所以打印的是B->1
总结:
A subclass inherits rewrite parent function
1.接口继承(B不写virtual还是虚函数,符合多态条件,And the default value is the parent class)
2.Rewrite the function
But oh, look at a problem,Same as above but call changed
这道题是b->1还是b->0?
是b->0为什么?Because here is the common call,Not by polymorphism to call,So he didn't start conditions
看下面代码
class Person {
public:
~Person()
{
cout << "~Person()" << endl;
}
};
class Student : public Person {
public:
// PersonThe destructor addedvirtual,Relationship has changed
// 重定义(隐藏)关系 -> 重写(覆盖)关系
~Student()
{
cout << "~Student()" << endl;
delete[] _name;
cout << "delete:" << (void*)_name << endl;
}
private:
char* _name = new char[10]{
'j','a','c','k' };
};
int main()
{
// There is no influence for ordinary objects
//Person p;
//Student s;
// 期望delete ptrCalling the destructor is a polymorphic call
// If you design a class,可能会作为基类,Secondly the destructor is best defined as the virtual function
Person* ptr = new Person;
delete ptr; // ptr->destructor() + operator delete(ptr)
ptr = new Student;
delete ptr; // ptr->destructor() + operator delete(ptr)
return 0;
}
打印结果
调用了一个person和一个student,When the destructor no callstudent,存在内存泄漏
Solutions will be simple as long as there is polymorphism can solve,In the parent class plusvirtualBecomes a polymorphic,Suggest a subclass also add,Although the subclass inherits parent virtual function
What will print below?
According to our previously learned thought is8
结果
16为什么是16,Because it is a virtual function virtual function will be a virtual function pointer,所以是32位下4+4+1对齐=12,64位下8+4对齐=16
3.final关键字
final: To prohibit rewrite keyword
finalCan write in the back of the class,But to write in the back of the class on behalf ofCar不能当父类
4.override关键字
override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错
5.重载,隐藏,重定义的对比
6.抽象类
在虚函数的后面写上 =0 ,则这个函数为纯虚函数.包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象.派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象.纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承.
// 抽象类 -- In reality there is no specific corresponding entities
// 不能实例化出对象
// 间接功能:Require a subclass needs to be rewritten,才能实例化出对象
class Car
{
public:
// 纯虚函数
virtual void Drive() = 0;
};
class BMW :public Car
{
public:
virtual void Drive()
{
cout << "BMW-操控" << endl;
}
};
class Benz :public Car
{
public:
virtual void Drive()
{
cout << "Benz-舒适" << endl;
}
};
int main()
{
Car c;
BMW b;
return 0;
}
运行结果
Rewrite can invoke the subclass
不重写会报错
7.多态原理
We spoke above ticket system simulation to achieve this node finally spoke behind the virtual function has a virtual function pointer
代码
class Base
{
public:
virtual void Func1()
{
cout << "Base::Func1()" << endl;
}
virtual void Func2()
{
cout << "Base::Func2()" << endl;
}
void Func3()
{
cout << "Base::Func3()" << endl;
}
private:
int _b = 1;
};
class Derive : public Base
{
public:
virtual void Func1()
{
cout << "Derive::Func1()" << endl;
}
void Func3()
{
cout << "Derive::Func3()" << endl;
}
private:
int _d = 2;
};
int main()
{
cout << sizeof(Base) << endl;
Base b;
cout << sizeof(Derive) << endl;
Derive d;
return 0;
}
通过上面代码我们可以知道Base b是Dereive d的父类
And they constitute the redefine,So they have a virtual function pointer,Look at the pictures below debugging
可以看到b和d的区别是在Func1不一样,为什么不一样
因为重写了Func1
总结:
虚函数重写 -语法层-Subclasses to rewrite the superclass virtual function to achieve
虚函数重写 -原理层-A subclass of the virtual table copies of the parent virtual table modified,Overwriting the virtual function
This is how to implement call,In fact he looked this call is not type,而是地址,
多态调用:运行时决议,To point to the object's virtual table check function address
普通调用:Try to compile the resolution,编译时确定函数地址
证明
可以看到上面Func1A subclass of print,但是Func3没有,因为Func3不是虚函数,Virtual table so no printing
8Why not achieve object polymorphism,Pointers and references can be
因为编译时,Determines the object not achieve the polymorphic,不满足要求,If forced object can realize polymorphic will appear below the case
It invokes the constructor when object section of the,Subclasses will only copy the parent class members,不会拷贝虚表指针,If you copy the virtual table pointer is confused,为什么?Because this time the parent class's virtual table pointer of the parent class or subclass of don't know,And Pointers and references when they how to implement polymorphism of,They have a virtual table pointer address,When calling the polymorphism of the virtual table pointer,What they call a virtual table pointer.After all, what the address is what
When shown below from inside the disassembly representative polymorphic query virtual table call
When didn't constitute a polymorphism of the disassembly code below
8.And the static and dynamic binding binding concept
- 静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为,也称为静态多态,比如:函数重载
- 动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态.
1.Watch window to hide
西面Func4Is there no inside the virtual table,Watch window also did not seeFunc4的虚表
答案是有的,Because the watch window is processed by a compiler was practically see is not very accurate,Look at the situation really is the memory window
I guess below,But this is just guess the not necessarily correct,So we write a function to verify the validation
代码
class Base
{
public:
virtual void Func1()
{
cout << "Base::Func1()" << endl;
}
virtual void Func2()
{
cout << "Base::Func2()" << endl;
}
void Func3()
{
cout << "Base::Func3()" << endl;
}
private:
int _b = 1;
};
class Derive : public Base
{
public:
// 重写
virtual void Func1()
{
cout << "Derive::Func1()" << endl;
}
void Func3()
{
cout << "Derive::Func3()" << endl;
}
virtual void Func4()
{
cout << "Derive::Func4()" << endl;
}
private:
int _d = 2;
};
// 取内存值,打印并调用,确认是否是func4
typedef void(*V_FUNC)();
// 打印虚表
//void PrintVFTable(V_FUNC a[])
void PrintVFTable(V_FUNC* a)
{
printf("vfptr:%p\n", a);
for (size_t i = 0; a[i] != nullptr; ++i)
{
printf("[%d]:%p->", i, a[i]);
V_FUNC f = a[i];//Function addresses directly call the function
f();
}
}
int c = 2;
int main()
{
Derive d;
PrintVFTable((V_FUNC*)(*((int*)&d)));
return 0;
}
Print results and the monitoring window address the same,Said we write on behalf of the right,And there was no give you that didn't constitute monitor window polymorphicfunc4,但func4There is a virtual table address,But the above codePrintVFTable((V_FUNC*)(((int)&d)));如果是32位就用4字节的,如果是64位就用8字节的类型
2.Virtual table exists that position
首先我们先了解,虚表,一个类型,一个虚表,所以这个类型对象都存这个虚表指针
因为这样,The stack is impossible to store,Because the stack frame a scope is destroyed,Then how can find virtual table pointer
Heap is not likely to,Pile of open Spaces can be,But the release of what to do?
So can only in static area or the constant area,Because they spent the runtime,But I feel a little bit constant area more accord with,Because there is no change the virtual table,But said don't have to use the program to confirm
Can see is in constant area
边栏推荐
- HCIP第十七天笔记
- DOM对象能干什么?
- Dry goods!A highly structured and sparse linear transformation called Deformable Butterfly (DeBut)
- 跨链桥协议 Nomad 遭遇黑客攻击,损失超 1.5 亿美元
- Binary search tree (search binary tree) simulation implementation (there is a recursive version)
- OS层面包重组失败过高,数据库层面gc lost 频繁
- Skills required to be a good architect: How to draw a system architecture that everyone will love?What's the secret?Come and open this article to see it!...
- type="module" you know, but type="importmap" you know
- QT with OpenGL(HDR)
- Boolean 与numeric 无法互转
猜你喜欢
随机推荐
VL53L0X V2 laser ranging sensor collects distance data serial output
SAP 电商云 Spartacus UI 的 External Routes 设计明细
程序员架构修炼之道:如何设计出可持续演进的系统架构?
浪潮—英伟达打造元宇宙新方案,虚拟人的故事将再破你的认知
混动产品谁更吃香,看技术还是看市场?
被审稿人吐槽没有novelty!深度学习方向怎么找创新点?
关于OPENSSL的问题
LeetCode_多叉树_中等_429.N 叉树的层序遍历
进入 SQL Client 创建 table 后,在另外一个节点进入 SQL Client 查询不到
mysql数据库定时备份占用大量线程,导致全局锁表,有啥好的解决方法么
[华为云在线课程][SQL语法入门][学习笔记]
鸿蒙第三次
APENFT FOUNDATION官宣2022艺术梦想基金主题征集
MySQL binlog的这种时间怎么处理呢??
Mysql OCP 72题
servlet生命周期详解--【结合源码】
type=“module“ 你了解,但 type=“importmap“ 你知道吗
MySQL数据库基本使用
完全背包问题
Guys, I have a problem: My source mysql has a table that has been writing to, I use mysql cdc connec