神奇的多态

本文探讨了C++中如何实现多态性,重点介绍了使用虚函数、dynamic_cast及typeid的方法,并通过示例代码展示了如何在不使用virtual的情况下实现多态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++中多态表示通过一个public基类的指针或引用,来得到一个衍生类对象,并希望同一方法根据对象的不同而有不同的行为。一般来说多态需要搭配2种方式来使用:

1、经过隐式转换操作,把衍生类的指针或引用转换为public基类的指针或引用。

如 class A{...};class B:public A{...};

A& a1=b;

2、使用虚函数(virtual function)。

编译器通过在class中扩充一个指向虚函数表的指针来支持动态联编。当然这比起不使用virtual来说无论从空间还是时间来说效率都比较低。

其实还有一种方法可以不使用virtual来实现多态,当然这需要在runtime付出开销。就是使用类型转换。

C++中有四种类型转换符,分别是static_cast、dynamic_cast、reinterpret_cast、和const_cast。

dynamic_cast:动态类型转换,一般用在父类和子类指针或应用的互相转化; 

static_cast:静态类型转换,一般是普通数据类型转换(如int m=static_cast(3.14)); 

reinterpret_cast:重新解释类型转换,很像c的一般类型转换操作; 

const_cast:常量类型转换,是把cosnt或volatile属性去掉。 

就先只谈一下dynamic_cast,它可以用来回答:“是否可以安全的将对象的地址赋给特定类型的指针。如果可以运算符将返回对象的地址,否则将返回一个空指针。通常安全的类型指type或type的衍生类型:dynamic_cast<type*>(*p)。

当然也可以将一个dynamic_cast用于引用,如果失败时,它将抛出bad_cast exception。

哦,还可以使用typeid运算符,它能够确定两个对象是否为同种类型,接受两个参数: 1、类名;

2、结果为对象的表达式。

typeid返回一个对type_info对象的引用,type_info类重载了= =和!=运算符,来对类型进行比较。如果为空指针则抛出bad_typeid exception。

使用type_info和dynamic_cast可以避免virtual。

代码如下:

 

#include <iostream>
using namespace std;
class A{
public:
	void virtual p(){ cout << "A"<<endl; }
	void q(){ cout << "Aq" << endl; }
};
class B :public A{
public:
	void p(){ cout << "B" << endl; }
	void q(){ cout << "Bq" << endl; }
};
int main(){
	B b = B();
	A a = b;
	b.p();
	a.p();
	A& a1 = b;
	a1.p();
	b.q();
	a.q();
	a1.q();

	A* ap = new B();
	ap->p();
	ap->q();
	if (B *bp1 = dynamic_cast<B*>(ap))
	{
		bp1->p();
		bp1->q();
	}
	if (typeid(B)==typeid(*ap))
	{
		B* bp2=(B*)ap;
		bp2->p();
		bp2->q();
	}
	delete ap;
	cin.get();
	return 0;
}
运行情况如下:

与Java不同,在Java中直接使用类名就可以使用多态,而c++却需要指针或引用,原因在于他们并不引发内存中任何“与类型有关的内存委托操作”,受到改变的只是它们所指向的内存的“大小和内容解释方式”。如果直接将一个衍生类对象赋给一个基类对象的话,那将引发切割,衍生类会被切割并塞入基类对象的内存中,多态将消失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值