动态多态:C++动态多态是利用虚函数特性实现的,即基类指针(引用)指向派生类指针(引用)。由于虚函数的实现是在运行期进行的,因而会产生运行期开销(虚表指针偏移,与分支预测器和CPU指令流水线相关)。除此之外,虚函数的存在还会使得每个类中增加一个虚表和指向虚表的指针,这又将导致内存开销。
静态多态:顾名思义,编译时多态,避免虚函数开销。由于基类能够在编译时获得派生类的类型,因此也能在编译时对派生类的函数进行派发。
// 这里为了简化代码,只演示静态多态,故暂未考虑CRTP易错点:派生的基类模板参数不是派生类
template <typename T>
class Animal
{
public:
void eat()
{
static_cast<T *>(this)->eat();
}
};
class Cat : public Animal<Cat>
{
public:
void eat()
{
std::cout << "猫吃鱼" << std::endl;
}
};
class Dog : public Animal<Dog>
{
public:
void eat()
{
std::cout << "狗啃骨头" << std::endl;
}
};
// 由于类型是在编译时确定的,因而多态调用也是在编译时调用的
// 为什么不用template T void eat(T &animal),不是也可以实现静态多态?
// 原因是模板基类可以起到接口类的作用,约束函数参数animal的类型必须派生自Animal
template <typename T>
void eat(Animal<T> &animal)
{
animal.eat();
}
int main(void)
{
Dog dog;
Cat cat;
eat(dog);
eat(cat);
system("pause");
return 0;
}