C++多态和强制转换

f45qwnt8  于 2023-04-01  发布在  其他
关注(0)|答案(1)|浏览(127)

我正在尝试通过转换来弄清楚多态性的行为。使用下面的代码,你能向我解释为什么“child〉parent〉child”指令序列是可以的,而“parent〉child”序列不是(chd 3变量在dynamic_cast之后为null)?

#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我希望Parent〉child dynamic_cast是OK的,因为我在互联网上发现,如果类具有多态性,它就可以了。

hof1towb

hof1towb1#

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 child\n"; }

    virtual void squabble() { std::cout << "kids squabble\n"; }
};

有了这样的层次结构,你可以使用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的使用是相当不寻常的。如果你最终经常使用它,很有可能你有一个设计问题。

相关问题