类型转换之动态转型(dynamic_cast)
多态可以扩展到每一个对象可以动态的被识别,从而区分类型做只有该类型才有的操作,而不是虚函数规定的操作,这要依赖于类型的动态转换。例如一个Account * 的容器中,针对以下对象进行操作:Savings类对象,余额增加以1%计算的利息。Checking类对象,余额增加以0.05%计算利息。
Demo代码如下:
inline string getName() { return name; }
inline double getAmount() { return amount; }
virtual void add(double a)
{
amount += a;
}
};
class Saving : public Account
{
public:
Saving(string name) : Account(name) {}
void add(double a)
{
amount += a;
}
};
class Checking : public Account
{
public:
Checking(string name) : Account(name) {}
void add(double a)
{
amount += a;
}
};
int main()
{
vector<Account *> list;
Checking c("Checking user");
c.add(100);
Saving s("Saving user");
s.add(200);
list.push_back(&c);
list.push_back(&s);
Checking * pc;
Saving * ps;
int size = list.size();
for (int i = 0; i < size; ++i)
{
pc = dynamic_cast<Checking *> (list[i]);
if (NULL != pc)
{
pc->add(pc->getAmount() * 0.05);
}
ps = dynamic_cast<Saving *> (list[i]);
if(NULL != ps)
{
ps->add(ps->getAmount() * 0.1);
}
}
for (int i = 0; i < size; ++i)
{
pc = dynamic_cast<Checking *> (list[i]);
if (NULL == pc)
{
cout << "Checking";
}
else
{
cout << "Saving";
}
cout << " Account : " << list[i]->getName() << " = " << list[i]->getAmount() << endl;
}
return 0;
}
运行结果如下:
dynamic_cast操作是专门针对有虚函数的继承结构来的,它将基类指针转换成想要的子类指针,以做好子类操作的准备,因为各个不同的子类,其操作可能是不同的。上述程序中的pc->add(pc->getAmount() * 0.05);是针对Checking对象的操作。ps->add(ps->getAmount() * 0.1);是针对Saving对象的操作。
dynamic_cast操作所针对的基类指针,如果所指向的对象中不含有想要的子类对象,则将得到NULL(NULL是个宏定义#define NULL 0)值的结果。
即:
Saving s("Saving user_s");
Account * pa = & s;
Checking * pc = dynamic_cast<Checking *> (pa);
此时pc == NULL的
据此,判断转换后的指针是否为零,就能排除不必要的操作错误而把握地进行想要的操作,当然,任何其他的不符合多态类要求的对象,或者NULL指针,其转换的结果也都归为NULL;这在编程中,在应该不应该使用dynamic_cast时首先就要注意。例如,假设Student类是没有虚函数的基类,GraduateStudent类继承了它,则下列代码通过Student类的指针,就甭想得到GraduateStudent类对象的显示操作:
Student S("Jenny");
GraduateStudent gs("Smith");
Student * ps = dynamic_cast<Student *> (&gs);
ps->display();
其调用的结果还是Student的成员函数,而不是GraduateStudent的成员函数。