C++的动态多态与静态多态

Posted 飞鹤0755

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++的动态多态与静态多态相关的知识,希望对你有一定的参考价值。

1. 概述

C++是一门面向对象的编程语言。面向对象的一个最重要特征,即面向接口编程。面向接口编程,可以降低代码的耦合度,提高维护代码的可靠性。而面向接口编程是通过多态这一语言特征来实现的。

2. 动态多态

2.1. 概念

顾名思义,动态多态,即在运行时,也即代码执行时表现出来的多种状态。

  • 在语法层面,是通过使用virtual标记基类的函数,然后在派生类中重写此函数。在代码执行时,通过基类指针或引用的真实派生类型来调用派生类中的实现。
  • 在实现层面,主要是通过虚函数表来实现的。基类有virtual函数,则有一个虚函数表,那么派生类也会有一上自己的虚函数表。调用虚函数时,与指针类型无关,而与指针指向的具体是哪一个对象,调用的时候就会去查找相应对象的虚函数表,找到并执行相应虚函数。

class CUI
{
public:
	virtual ~CUI(){}
	virtual void OnPaint()
	{
		std::cout<< "Paint" <<std::endl;
	}
};

class CNormalUI : public CUI
{
public:
	virtual void OnPaint()
	{
		std::cout<< "Normal Paint" <<std::endl;
	}
};

class CColorUI : public CUI
{
public:
	virtual void OnPaint()
	{
		std::cout<< "Colorfullly Paint" <<std::endl;
	}
};

int main(int argc, char **argv)
{
	CUI* p = new CNormalUI();
	p->OnPaint(); // Normal Paint
	delete p;

	p = new CColorUI();
	p->OnPaint(); // Colorfullly Paint
	delete p;
	
	return 0;
}

2.2. 优点

  • 增加新的实现,不用修改以前的代码,减少对过往功能可靠性的影响。
  • 实现接口保持一致,可以更方便地添加新的实现。

2.3. 缺点

  • 动态多态是通过虚函数表来实现的,每个派生类实现的虚函数并不固定,所以虚函数表大小并不固定,这就导致每次虚函数的调用,都需要有一个查找虚函数表的过程,这就导致调用虚函数的性能会降低。
  • 虚函数表与普通成员函数的内存分配并不是在一起的,也就是说虚函数表的设计并不是Cache友好型设计,这就导致CPU的流水线在执行代码时,代码的命中效率会降低,降低虚函数的调用性能。

3. 静态多态

3.1. 概念

静态多态,是指在编译期间实现的多态。有人将函数重载理解为静态多态,但是函数重载要求形参不同,这与虚函数实现的多态有较大差异。此处讲的静态多态,与虚函数实现的动态多态类型,函数名相同,函数参数也相同。这主要是通过一种CRTP(curiously recurring template pattern)技术来实现的,即一个类X派生自以X为模板形参的类模板实例。
下面的代码,主要依靠模板实例化时才编译,以及派生类可以访问基类模板类中的成员及方法。需要注意的是,派生类函数的调用是通过强制类型转换来实现的,这里的强制转换是不安全的,所以派生类实现无法访问派生类中的其他成员。

template<class T>
class CUI
{
public:
	void OnPaint()
	{
		static_cast<T&>(*this).OnPaintImpl();
	}

	void OnPaintImpl()
	{
		std::cout<< "Paint" <<std::endl;
	}
};

class CNormalUI : public CUI<CNormalUI>
{
public:
	void OnPaintImpl()
	{
		std::cout<< "Normal Paint" <<std::endl;
	}
};

class CColorUI : public CUI<CColorUI>
{
public:
	void OnPaintImpl()
	{
		std::cout<< "Colorfullly Paint" <<std::endl;
	}
};

int main(int argc, char **argv)
{
	CUI<CNormalUI> ui1;
	ui1.OnPaint();

	CUI<CColorUI> ui2;
	ui2.OnPaint();
	
	return 0;
}

4. 比较

  • 动态多态更加灵活,适合更复杂的应用场景。
  • 静态多态是编译期实现的多态,效果更高,适用于对性能要求高的场景,如UI渲染等。

以上是关于C++的动态多态与静态多态的主要内容,如果未能解决你的问题,请参考以下文章

C++静态多态与动态多态的实现原理剖析

9-3:C++多态之多态的实现原理之虚函数表,虚函数表指针静态绑定和动态绑定

如何在 C++ 中用静态多态性代替动态多态性?

C++类和对象--多态

C++多态 --- 多态实现原理简析

C++ 多态 : 虚函数静态绑定动态绑定单/多继承下的虚函数表