C++ 编译时多态和运行时多态

本文深入探讨了C++中的两种多态形式:编译时多态(静态多态)和运行时多态(动态多态)。静态多态主要通过模板和函数重载实现,无需继承关系,而动态多态依赖于类继承和虚函数,利用虚函数表在运行时确定函数调用。动态多态增加了内存开销,但能处理异质对象集合,而静态多态在编译期间即可确定,提高了效率,但无法实现异质对象的处理。两者各有优缺点,适用于不同的场景。
摘要由CSDN通过智能技术生成

前言
    多态多为C++的三大特性之一,我们对此的了解和应用大多停留在类继承层次和运行时阶段。那既然有运行(动态)时阶段,那是否也有静态的多态?有,那就是编译时多态

正文
  动态多态

    运行时的多态存在于继承类中,通过虚函数实现动态选择调用。简单的说就是通过一张虚函数表——vptable,vptable中记录了基类的虚函数地址,在派生类中继承了基类的这张vptable,而且在派生类的构造函数中对继承来的vptable相关地址进行替换,因此在调用时通过vptable的实际地址能够知道调用哪个函数。下面是个简单的范例:

#pragma once
 
#include <iostream>
class CBase
{
public:
	CBase(){std::cout<<"CBase::CBase"<<std::endl;}
	~CBase(){std::cout<<"CBase::~CBase"<<std::endl;}
 
	virtual int getMax(int a, int b)
	{
		std::cout<<"CBase::getMax"<<std::endl;
		return a>b?a:b;
	}
};
 
class CChild : public CBase
{
public:
	CChild(){std::cout<<"CChild::CChild"<<std::endl;}
	~CChild(){std::cout<<"CCHild::~Child"<<std::endl;}
 
	virtual int getMax(int a, int b)
	{
		std::cout<<"CChild::getMax"<<std::endl;
		return a>b?a:b;
	}
};
 
void main()
{
	CBase *pBase = new CBase;	
	CChild *pChld = new CChild;
	pBase->getMax(5, 2);
	pBase = new CChild;
	pBase->getMax(5,2);
	getchar();
	return;
}

输出如下:

 

总之动态多态发生在继承关系的类中,通过虚函数表实现。那静态多态呢?

  静态多态

    静态多态是发生在编译时期的,通过模板和函数重载实现,相比动态多态不需派生关系。下面看一个范例

class Animal
{
public :
    void shout() { cout << "发出动物的叫声" << endl; };
};
class Dog
{
public:
     void shout(){ cout << "汪汪!"<<endl; }
};
class Cat
{
public:
     void shout(){ cout << "喵喵~"<<endl; }
};
class Bird
{
public:
     void shout(){ cout << "叽喳!"<<endl; }
};
template <typename T>
void  animalShout(T & t)
{
    t.shout();
}
int main()
{
    Animal anim;
    Dog dog;
    Cat cat;
    Bird bird;
 
    animalShout(anim);
    animalShout(dog);
    animalShout(cat);
    animalShout(bird);
 
    getchar();
}

上例就是通过模板实现静态多态,重载范例就不展示了。那么这两者区别在于什么?

 

编译时多态和运行时多态区别:

1、运行时体现了面向对象的思想,但是虚函数表增加了内存开销

2、运行时多态发生在运行时期,所以编译器无法进行优化处理

3、编译时多态运用泛型编程,在编译器完成提升运行期效率,但是无法实现模板的分离编译所以对于大工程而言编译耗时

4、编译时多态无法处理异质对象集合(什么是异质对象?)

 

延申拓展:显示接口和隐士接口

    显示接口就是指能够明确来源的接口,比如在动态多态的范例中,当调用getMax时,我们能够知道这个getMax到底是CBase的还是CChild的

    隐式接口就是指那些无法确定的来源的接口,如对于函数重载和模板,我们也不知道调用的是哪个实现。

 

解答:

    异质类:就是(存储、指向)类型不一致的数据对象,如pBase,或Template<type T>,所以异质类的实现核心就是多态+模板编程
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金州饿霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值