您的位置:首页 > 编程语言 > C语言/C++

神奇的多态

2015-12-30 09:20 169 查看
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++却需要指针或引用,原因在于他们并不引发内存中任何“与类型有关的内存委托操作”,受到改变的只是它们所指向的内存的“大小和内容解释方式”。如果直接将一个衍生类对象赋给一个基类对象的话,那将引发切割,衍生类会被切割并塞入基类对象的内存中,多态将消失。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ Java 多态 博客