我正试图找出多态与铸造的行为。使用下面的代码,你能向我解释为什么"子"父母在child"指令序列是OK的,并且"父指令"child"序列不是(chd3变量在dynamic_cast之后为空)?
#include <iostream>
using namespace std;
class Parent {
public:
virtual void speak() {};
};
class Child : public Parent {
public:
virtual void speak() override {
cout << "Yeah !" << endl;
};
};
int main(int argc, char* argv[]) {
// ----------------------
// child > parent > child : OK
Child* chd1 = new Child;
Parent* prt1 = dynamic_cast<Parent*>(chd1); if (prt1 == nullptr) { cout << "prt1 ERROR" << endl; return 1; }
prt1->speak();
Child* chd2 = dynamic_cast<Child*>(prt1); if (chd2 == nullptr) { cout << "chd2 ERROR" << endl; return 1; }
chd2->speak();
// parent > child : NOK : raises ptrnull value
Parent* prt2 = new Parent;
Child* chd3 = dynamic_cast<Child*>(prt2); if (chd3 == nullptr) { cout << "chd3 ERROR" << endl; return 1; };
// debug
cin.get();
// return
return 0;
}
谢谢你!
(Was expected parents>child dynamic_cast是OK的,因为我在互联网上发现,如果类具有多态性,它将是OK的。
dynamic_cast
的全部意义在于检查所涉及对象的动态类型,以确定强制转换是否能够成功。
从Child *
到Parent *
不需要使用dynamic_cast
。您可以隐式地向那个方向转换,因此根本不需要强制转换。
Parent *p = new child; // no problem.
dynamic_cast
在另一个方向上是有用的。你有一个Parent *
,但你不确定它指向的是Parent
还是Child
。因此,您可以尝试使用dynamic_cast
进行转换,并且当且仅当它指向的对象是Child
时,转换才会成功。
Parent *p1 = new Parent;
Parent *p2 = new Child;
Child *p3 = dynamic_cast<Child *>(p1); // should fail (give a null pointer)
Child *p4 = dynamic_cast<Child *>(p2); // should succeed.
话虽如此,dynamic_cast
的实际用途是相当不寻常的。继承的主要目的是允许您使用指向基类的指针(或引用),但通过在基类中声明虚函数并在派生类中实现虚函数来获得特定于派生类的行为。dynamic_cast
主要用于派生类添加了根本不在基类中的不同功能的情况。
class Person {
public:
virtual void speak() = 0;
};
class Child : public Person {
public:
virtual void speak() { std::cout << "I'm a childn"; }
virtual void squabble() { std::cout << "kids squabblen"; }
};
使用这样的层次结构,您可以使用dynamic_cast
。每个人都会说话,但只有孩子才会争吵。所以你可以这样写:
Person *p = new Child;
p->speak(); // no problem a Person can speak
// but only a child can squabble:
Child *c = dynamic_cast<Child *>(p);
if (c != nullptr)
c->squabble();
但我要重复:dynamic_cast
的使用是相当不寻常的。如果你最终经常使用它,很有可能你有一个设计问题。