当前位置:网站首页>多态的所有特征
多态的所有特征
2022-06-11 21:36:00 【爱学代码的学生】
1. 什么是多态
同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。
简单的说:就是用基类的引用或者指针指向子类的对象
2. 多态的基本语法
基类的指针或者引用执行子类的对象
//动物类
class Animal
{
public:
//虚函数
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
//猫类
class Cat :public Animal
{
public:
virtual void speak()
{
cout << "小猫在说话" << endl;
}
};
class Dog :public Animal
{
public:
virtual void speak()
{
cout << "小狗在说话" << endl;
}
};
//父类的指针或者引用来执行子类的对象
void dospeak(Animal& animal)
{
animal.speak();
}
void test()
{
Cat cat;
dospeak(cat);
Dog dog;
dospeak(dog);
}
int main()
{
test();
return 0;
}3. 多态的底层原理
多态的实现原理是:
1.有继承关系
2.子类要重写父类中的虚函数
什么是虚函数呢?
被virtual关键字修饰过的函数称为虚函数
那么在底层,类中拥有被virtual修饰过的函数会产生什么呢?

我们发现类中会产生一个vfptr的指针和一个名为vftable的作用域,这个指针指向这个作用域,而在这个作用域中存在着被virtual修饰的函数的地址
那么子类为什么要重写父类中的虚函数呢?

我们发现,如果没有重写父类中的虚函数,那么在子类将继承父类中的vftable,那么在调用speak函数时,永远调用的是父类中实现的函数
4. 纯虚函数和抽象类
什么是纯虚函数?
在多态中,我们会发现基类实现的代码基本上是用不到的,那么我们就可以将其设置成纯虚函数
纯虚函数的语法:virtual 返回值 函数名()= 0
class Base
{
public:
//纯虚函数
virtual void func() = 0;
};什么是抽象类?
当一个类中存在了纯虚函数,那么这个类就被称做抽象类
抽象类有什么特点呢?
1. 抽象类无法进行实例化
2. 如果抽象类的子类没有重写纯虚函数,那么该子类也无法进行实例化
5. 纯虚析构和虚析构函数
这里我们先看一段代码:
class Animal
{
public:
Animal()
{
cout << "调用Animal的构造函数" << endl;
}
virtual void speak() = 0;
~Animal()
{
cout << "调用Animal 的析构函数" << endl;
}
};
{
cout << "调用Animal的析构函数" << endl;
}
class Cat :public Animal
{
public:
Cat(string name)
{
cout << "调用Cat的构造函数" << endl;
_name = new string(name);
}
virtual void speak()
{
cout << *_name<<"猫会说话" << endl;
}
string* _name;
~Cat()
{
cout << "调用Cat的析构函数" << endl;
if (_name != NULL)
{
delete _name;
}
}
};
void test()
{
Animal* c = new Cat("Tom");
c->speak();
delete c;
}
int main()
{
test();
return 0;
}
我们发现当删除c对象时,没有调用子类中的析构函数,而子类中又申请了堆上的空间,那么这样就会造成内存泄漏
那么我们如何保证调用子类中的析构函数呢?
这里我们就需要在父类的析构函数前面加上virtual来修饰
class Animal
{
public:
//纯虚函数
Animal()
{
cout << "调用Animal的构造函数" << endl;
}
virtual void speak() = 0;
//虚析构和纯虚析构都需要代码的实现
virtual ~Animal()
{
cout << "调用Animal的析构函数" << endl;
}
};
class Cat :public Animal
{
public:
Cat(string name)
{
cout << "调用Cat的构造函数" << endl;
_name = new string(name);
}
virtual void speak()
{
cout << *_name<<"猫会说话" << endl;
}
string* _name;
~Cat()
{
cout << "调用Cat的析构函数" << endl;
if (_name != NULL)
{
delete _name;
}
}
};
void test()
{
Animal* c = new Cat("Tom");
c->speak();
delete c;
}
int main()
{
test();
return 0;
}
上面我们使用的是虚析构函数来帮助我们解决内存泄漏的问题,这里我们也可以使用纯析构函数来帮助我们
#include"多态.h"
class Animal
{
public:
//纯虚函数
Animal()
{
cout << "调用Animal的构造函数" << endl;
}
virtual void speak() = 0;
virtual ~Animal() = 0;
};
class Cat :public Animal
{
public:
Cat(string name)
{
cout << "调用Cat的构造函数" << endl;
_name = new string(name);
}
virtual void speak()
{
cout << *_name<<"猫会说话" << endl;
}
string* _name;
~Cat()
{
cout << "调用Cat的析构函数" << endl;
if (_name != NULL)
{
delete _name;
}
}
};
void test()
{
Animal* c = new Cat("Tom");
c->speak();
delete c;
}
int main()
{
test();
return 0;
}当我们这样去写的时候,我们会发现编译器会报链接的错误

在使用虚析构来解决问题的时候,我们发现编译器也会调用父类中的析构函数,如果函数中没有进行代码实现,那么就会报错,所以无论是虚析构还是纯虚析构,我们都需要对其进行代码的实现
Animal::~Animal()
{
cout << "调用Animal的析构函数" << endl;
}当在类外实现了纯虚析构的实现,编译器就不再会报错
总结:
纯虚析构函数和虚析构函数的共性:
1.可以解决父类指针释放子类对象不干净的问题
2.都需要具体的代码实现
纯虚析构函数和虚析构函数的不同:
1.如果一个类中存在纯虚析构,这个类处于抽象类,不能进行实例化
2.如果是虚析构,仍可以进行实例化
注:
如果子类中没有堆区的数据,可以不用写纯虚析构或者虚析构
边栏推荐
- Leetcode-322- change exchange
- 如何将SAP API Hub 上提供的工作流导入到 SAP BTP 上
- Release of version 5.6 of rainbow, add multiple installation methods, and optimize the topology operation experience
- 作为一名 ABAP 资深顾问,下一步可以选择哪一门 SAP 技术作为主攻方向?
- 杭电中超9 1006 Guess the Weight
- RPA+低代码为何是加速财务数字化转型之利器?
- 【C語言進階】整型在內存中的存儲
- JVM | introduction
- Chain storage structure of linear table
- table_ Display status
猜你喜欢

RPA+低代码助推品牌电商启新创变、重启增长

LeetCode-110-平衡二叉树

即将首发 | 业界首个零售数字化创新白皮书,解锁全链路数字化致胜秘籍

【 C Advanced language】 Integer Storage in Memory

JVM|虚拟机栈(局部变量表;操作数栈;动态链接;方法的绑定机制;方法的调用;方法返回地址)

如何利用RPA机器人开启货代行业数字化转型第一步?

Leetcode-98- validate binary search tree

LeetCode-76-最小覆盖子串
![[Part 15] use and basic principle of forkjoinpool [key]](/img/36/e21b16ec92d444149bc793f340f9f3.jpg)
[Part 15] use and basic principle of forkjoinpool [key]

Goto statement of go language
随机推荐
I haven't blogged for two months. I sent an article to prove that my account is still alive
JVM heap
BZOJ3189 : [Coci2011] Slika
BUG -- coredump使用
[Part 14] source code analysis and application details of completionservice class [key]
Solve the problem of img 5px spacing
LeetCode-155-最小栈
Application business layer modification
Redis basic data type (hash)
JVM | introduction
Leetcode-76- minimum covering substring
俩月没发过博客了,发一篇证明自己的账号还活着
Leetcode-129- sum of numbers from root node to leaf node
Educational Codeforces Round 114 (Rated for Div. 2) D
一步步把 SAP UI5 应用部署到 SAP BTP Kyma 运行环境中去
实验10 Bezier曲线生成-实验提高-交互式生成B样条曲线
Goto statement of go language
Redis basic data type (Zset) ordered collection
JVM | virtual machine stack (local variable table; operand stack; dynamic link; method binding mechanism; method call; method return address)
八、BOM - 章节课后练习题及答案
