多态分为两类
静态多态:函数重载和运算符重载属于静态多态复用函数名
动态多态: 派生类和虚函数实现运行时多态。
静态多态和动态多态区别
静态多态的函数地址早绑定:编译阶段确定函数地址
动态多态函数地址晚绑定:运行阶段确定函数位置
class AnimalBase{
public:
int m_age;
// 虚函数 函数在运行阶段绑定
virtual void speek() {
cout << "AnimalBase speek" << endl;
}
};
class Dog : public AnimalBase
{
void speek() override {
cout << "dog speek" << endl;
}
};
class Pag : public AnimalBase {
void speek() override {
cout << "Pag speek" << endl;
}
};
//
void doWork(AnimalBase &animal) {
animal.speek();
}
void test58() {
Pag p;
doWork(p);
Dog d;
doWork(d);
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
test58();
std::cout << "end!\n";
return 0;
}
动态多态满足条件
1.有继承关系
2.重写父类中的虚函数 (返回值 函数名 参数列表 完全一致)
动态多态使用
父类的指针或者引用 指向子类对象。
多态原理
当类中有虚函数的时候 类里面会有一个虚函数表指针。指向虚函数表
vfptr v virtual f function ptr 指针
当子类继承于父类的时
没有重写虚函数
子类会从父类继承虚函数表
当重写后
子类虚函数表内部会替换成子类虚函数表地址
当父类的指针或者引用指向子类的时候就发生了多态
上边是父类的 内部结构图
下边是没有重写时类的内部结构图
重写后类的内部结构图
多态案例
多态的好处
1.组织结构清晰
2.可读性强
#include <iostream>
#include <string>
using namespace std;
class AbstureCalculator {
public:
int m_num1;
int m_num2;
virtual int getResult() {
return 0;
};
};
class SumCalculator : public AbstureCalculator {
int getResult() override {
return m_num1 + m_num2;
}
};
class MinusCalculator : public AbstureCalculator {
int getResult() override {
return m_num1 - m_num2;
}
};
class MulCalculator : public AbstureCalculator {
int getResult() override {
return m_num1 * m_num2;
}
};
void test60() {
AbstureCalculator *calculator = new SumCalculator;
calculator->m_num1 = 100;
calculator->m_num2 = 2000;
cout << calculator->getResult() << endl;
delete calculator;
calculator = new MinusCalculator;
calculator->m_num1 = 2000;
calculator->m_num2 = 100;
cout << calculator->getResult() << endl;
delete calculator;
calculator = new MulCalculator;
calculator->m_num1 = 2000;
calculator->m_num2 = 100;
cout << calculator->getResult() << endl;
delete calculator;
}
// 普通写法
class Calculator {
public:
int m_num1;
int m_num2;
int getResult(string oper) {
if (oper == "+") {
return m_num1 + m_num2;
} else if (oper == "-") {
return m_num1 - m_num2;
} else if (oper == "*") {
return m_num1 * m_num2;
} else if (oper == "/") {
return m_num1 / m_num2;
}
return 0;
};
};
void test53() {
Calculator c;
c.m_num1 = 100;
c.m_num2 = 200;
c.getResult("*");
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
test53();
test60();
std::cout << "end!\n";
return 0;
}
纯虚函数和抽象类
在多态中,通常父类中虚函数的实现是毫无意义的主要都是调用子类重写的内容
因此可以将虚函数改成纯虚函数。
纯虚函数的语法
virtual返回值类型 函数名(参数列表)=0;
当类中有了纯虚函数 这个类称为抽象类。
抽象类特点
无法实例化对象。
子类必须重写抽象类中的纯虚函数,否则也属于抽象类
#include <iostream>
#include <string>
using namespace std;
class Super {
public:
//纯虚函数
//只要有一个纯虚函数 这个类称为抽象类
//抽象类特点
//1.无法实例化对象
//2.抽象类必须重写纯虚函数否则也是抽象类
virtual void func() = 0;
};
class Son : public Super {
public:
void func() override {
cout << "virtual" << endl;
}
};
void test61() {
//Super s;//Variable type 'Super' is an abstract class
Son s;
s.func();
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
test61();
std::cout << "end!\n";
return 0;
}
#include <iostream>
#include <string>
using namespace std;
class AbstractDrink{
public:
virtual void boil() = 0;
virtual void brew() = 0;
virtual void cup() = 0;
virtual void putSome() = 0;
void makeDrink() {
boil();
brew();
cup();
}
virtual ~AbstractDrink(){
}
};
class coffe : public AbstractDrink {
public:
void boil() override {
cout << "煮水" << endl;
}
void brew() override {
cout << "加入coffe" << endl;
}
void cup() override {
cout << "放入杯子" << endl;
}
void putSome() override {
cout << "加入辅料 " << endl;
}
};
class Tea : public AbstractDrink {
public:
void boil() override {
cout << "煮水" << endl;
}
void brew() override {
cout << "加入茶叶" << endl;
}
void cup() override {
cout << "放入杯子" << endl;
}
void putSome() override {
cout << "加入柠檬 " << endl;
}
};
void doMakeDrink(AbstractDrink *drink) {
drink->makeDrink();
}
void test62() {
AbstractDrink *drink = new coffe;
doMakeDrink(drink);
delete drink;
drink = new Tea;
doMakeDrink(drink);
delete drink;
// Delete called on 'AbstractDrink' that is abstract but has non-virtual destructor
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
test62();
std::cout << "end!\n";
return 0;
}
虚析构和纯虚析构
解决父类指针指向子类的时候 释放不干净的问题
若子类中没有堆区数据 可以不写虚析构或纯虚析构
拥有纯虚析构函数的类也属于抽象类
#include <iostream>
using namespace std;
class AbstractA {
public:
int *m_a;
virtual void info() = 0;
AbstractA(){
cout << "AbstractA init" << endl;
}
// // 虚析构
// virtual~AbstractA(){//Delete called on 'AbstractA' that is abstract but has non-virtual destructor
// cout << "~AbstractA()" << endl;
// }
//纯虚析构 必须要实现
virtual ~AbstractA() = 0;
};
AbstractA::~AbstractA(){
cout << "AbstractA::~AbstractA()" << endl;
}
class ClassB: public AbstractA {
public:
void info() override {
cout << *m_a << endl;
}
ClassB(int a) {
m_a = new int(a);
cout << "ClassB init" << endl;
}
~ClassB(){
if (m_a != nullptr) {
delete m_a;
}
cout << " ~ClassB()" << endl;
}
};
void test63() {
AbstractA *a = new ClassB(12);
a->info();
delete a;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
test63();
std::cout << "end!\n";
return 0;
}
#include <iostream>
#include "mathutil.hpp"
#include <string>
#include "People.hpp"
#include "Phone.hpp"
using namespace std;
class Cpu{
public:
virtual void calculate() = 0;
virtual ~Cpu(){
cout << "~Cpu" << endl;
}
};
class VideoCard{
public:
virtual void display() = 0;
virtual ~VideoCard(){
cout << "~VideoCard" << endl;
}
};
class Memory{
public:
virtual void storege() = 0;
virtual ~Memory(){
cout << "~Memory" << endl;
}
};
class Computer{
private:
Cpu *m_cpu;
VideoCard *m_videoCard;
Memory *m_memory;
public:
Computer(Cpu *cpu,VideoCard *card,Memory *m) {
m_cpu = cpu;
m_videoCard = card;
m_memory = m;
};
~Computer(){
if(m_cpu != nullptr) {
delete m_cpu;
}
if(m_videoCard != nullptr) {
delete m_videoCard;
}
if(m_memory != nullptr) {
delete m_memory;
}
}
void work() {
m_cpu -> calculate();
m_videoCard -> display();
m_memory -> storege();
}
};
class InterCpu: public Cpu {
public:
void calculate() override {
cout << "inter cpu 开始工作了" << endl;
}
virtual ~InterCpu(){
cout << "~InterCpu" << endl;
}
};
class InterVideoCard : public VideoCard {
public:
void display() override {
cout << "inter 显卡 开始工作了" << endl;
}
virtual ~InterVideoCard(){
cout << "~InterVideoCard" << endl;
}
};
class InterMemort : public Memory {
void storege() override {
cout << "inter 内存条 开始工作了" << endl;
}
virtual ~InterMemort(){
cout << "~InterMemort" << endl;
}
};
class DellCpu: public Cpu {
public:
void calculate() override {
cout << "Dell cpu 开始工作了" << endl;
}
virtual ~DellCpu(){
cout << "~DellCpu" << endl;
}
};
class DellVideoCard : public VideoCard {
public:
void display() override {
cout << "Dell 显卡 开始工作了" << endl;
}
virtual ~DellVideoCard(){
cout << "~DellVideoCard" << endl;
}
};
class DellMemory : public Memory {
void storege() override {
cout << "Dell 内存条 开始工作了" << endl;
}
virtual ~DellMemory(){
cout << "~DellMemory" << endl;
}
};
void test64() {
Cpu *c = new InterCpu;
VideoCard *v = new InterVideoCard;
Memory *m = new InterMemort;
Computer *cvm = new Computer(c,v,m);
cvm->work();
delete cvm;
c = new DellCpu;
v = new DellVideoCard;
m = new DellMemory;
cvm = new Computer(c,v,m);
cvm->work();
delete cvm;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
test64();
std::cout << "end!\n";
return 0;
}