多态的基本概念
分类两类
- 静态多态:重载,复用函数名等
- 动态多态:派生类和虚函数实现运行时多态
动态多态(函数地址晚绑定):
- 有继承条件
- 子类重写父类的虚函数
- 应用时,父类的指针或引用,指向子类对象
class Animal
{
public:
virtual void speak()//动态多态
{
cout << "Animal is speaking" << endl;
}
};
class Cat : public Animal
{
public:
virtual void speak()
{
cout << "Cat is speking" << endl;
}
};
void doSpeak(Animal& animal)// Aimal& animal = cat
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
}
底层原理: 类内记录虚函数地址;
多态应用
class Calculator {
public:
int m_Number1;
int m_Number2;
virtual int getResult() {
return 0;
}
};
class AddCalculator :public Calculator
{
public:
int getResult()
{
return m_Number1 + m_Number2;
}
};
class MulCalculator :public Calculator
{
public:
int getResult()
{
return m_Number1 * m_Number2;
}
};
void test01()
{
Calculator* abc;
abc = new AddCalculator;//加法器
abc->m_Number1 = 10;
abc->m_Number2 = 20;
cout << abc->getResult() << endl;
delete abc;
abc = new MulCalculator;//乘法器
abc->m_Number1 = 10;
abc->m_Number2 = 20;
cout << abc->getResult() << endl;
}
int main()
{
test01();
return 0;
}
纯虚函数和抽象类
- 多态中,通常父类的虚函数实现是无意义的,主要是调用子类重写的内容
- 因此可以将虚函数改为纯虚函数
virtual 返回值类型 函数名 (参数表) = 0;
- 含有纯虚函数的类叫抽象类
- 抽象类无法实例化对象,子类必须重写抽象类中的纯虚函数,否则无法实例化
class Base
{
public:
virtual void func() = 0;
};
class Son : public Base
{
public:
void func()
{
cout << "rewrite the virtual function of it's parent" << endl;
}
};
void test01()
{
//Base b;//抽象类无法实例化对象
Son son;
son.func();
}
int main()
{
test01();
return 0;
}
-
虚类实例:制作饮品
class AbstractDrinking { public: virtual void Boil() = 0; virtual void Brew() = 0; virtual void PourInCup() = 0; virtual void PutSomeThing()= 0; virtual void makeDrinking() { Boil(); Brew(); PourInCup(); PutSomeThing(); } }; class Coffee : public AbstractDrinking { virtual void Boil() { cout << "Boil water" << endl; } virtual void Brew() { cout << "Brew coffee" << endl; } virtual void PutSomeThing() { cout << "put sugar" << endl; } virtual void PourInCup() { cout << "pur coffee in cup" << endl; } }; void doWork(AbstractDrinking& drinking) { drinking.makeDrinking(); } void test01() { Coffee coffee; doWork(coffee); } int main() { test01(); return 0; }
虚析构和纯虚析构
- 在多态中,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用子类的析构代码
- 解决方式:父类的析构函数改为虚析构和纯虚析构
class Animal
{
public:
Animal()
{
cout << "Animal call structor " << endl;
}
virtual ~Animal()
{
cout << "Animal call delete" << endl;
}
//纯虚析构
virtual ~Animal() = 0;
virtual void speak() = 0;
};
Animal:: ~Animal()
{
cout << "Animal call delete" << endl;
}
class Cat : public Animal
{
public:
string* m_Name;
Cat(string name)
{
cout << "Cat call structor" << endl;
m_Name = new string(name);
}
virtual void speak()
{
cout << "cat is speaking " << endl;
}
virtual ~Cat()
{
if (m_Name != NULL)
{
cout << "Cat call delete" << endl;
delete m_Name;
m_Name = NULL;
}
}
};
void test01()
{
Animal* animal = new Cat("Tome");// 父类指针
animal->speak();
delete animal;// 父类指针释放子类对象
}
int main()
{
test01();
return 0;
}
多态案例
class CPU
{
public:
virtual void calculate() = 0;
};
class GPU
{
public:
virtual void display() = 0;
};
class Memory
{
public:
virtual void storage() = 0;
};
class Computer
{
public:
CPU* m_Cpu;
GPU* m_Gpu;
Memory* m_Mem;
Computer(CPU* cpu, GPU* gpu, Memory* mem)
{
m_Cpu = cpu;
m_Gpu = gpu;
m_Mem = mem;
}
void work()
{
m_Cpu->calculate();
m_Gpu->display();
m_Mem->storage();
}
~Computer()
{
if (m_Cpu != NULL)
{
delete m_Cpu;
m_Cpu = NULL;
}
if (m_Gpu != NULL)
{
delete m_Gpu;
m_Gpu = NULL;
}
if (m_Mem != NULL)
{
delete m_Mem;
m_Mem = NULL;
}
cout << "computer call delete" << endl;
}
};
class IntelCPU :public CPU
{
public:
virtual void calculate()
{
cout << "the Intel CPU is calculating!" << endl;
}
};
class NvidiaGPU:public GPU
{
public:
virtual void display()
{
cout << "the NAVIDIA GPU diaplay the graph!" << endl;
}
};
class SumsamMemory : public Memory
{
public:
virtual void storage()
{
cout << "the samsum memery is storaging!" << endl;
}
};
void test01()
{
IntelCPU* cpu = new(IntelCPU);
NvidiaGPU* gpu = new(NvidiaGPU);
SumsamMemory* mem = new(SumsamMemory);
Computer cpt(cpu, gpu, mem);
cpt.work();
}
int main()
{
test01();
return 0;
}