c++ 什么时候使用dynamic_cast< T>?

dauxcl2d  于 2023-05-20  发布在  其他
关注(0)|答案(3)|浏览(114)

我知道dynamic_cast,但我真的想知道什么时候使用它?为什么不总是将适当的函数添加到基类中,并且总是可以访问所需的函数?
这是否有任何性能方面?
我写了一个小例子来说明这一点。如果基类A中没有纯虚函数myUniqueFunc(),则只能使用dynamic_cast调用派生类中的函数。所以我总是把这个函数包含在基类中…
此外,dynamic_cast需要大量开销,因此需要大量计算时间。

#include <iostream>
#include <vector>

class A
{
public:
    virtual void printSomething() { std::cout << "class A: hello." << std::endl; };
    virtual void myUniqueFunc() = 0 ;
    virtual ~A() {};
};

class B : public A
{
public:
    void printSomething() override { std::cout << "class B: hello." << std::endl; };
    void myUniqueFunc() { std::cout << "class B: Only I can do this..." << std::endl; }
    B() {};
    virtual ~B() {};

};

class C : public A
{
public:
    //void printSomething() override { std::cout << "class C: hello." << std::endl; };
    void myUniqueFunc() { std::cout << "class C: Only I can do this..." << std::endl; }
    C() {};
    ~C() {};
};

int main()
{
    std::vector<std::unique_ptr<A>> myObjects;
    myObjects.emplace_back(std::make_unique<B>());
    myObjects.emplace_back(std::make_unique<C>());
    myObjects.emplace_back(std::make_unique<B>());
    myObjects.emplace_back(std::make_unique<C>());
    myObjects.emplace_back(std::make_unique<B>());
    myObjects.emplace_back(std::make_unique<C>());

    // 1. fast solution via complete virtual functions in base class
    // iterate over all Objects (common functions only
    for (auto& curObjects : myObjects)
    {
        curObjects->printSomething();
        curObjects->myUniqueFunc();
    }

    
    // 2. slow solution via incomplete virtual functions in base class and downcast to derived classes
    // iterate over all Objects (and calls the special func from the derived classes only)
    for (auto& curObjects : myObjects)
    {
        // downcast to the derived classes to get the unique functions
        if (typeid(curObjects) == typeid(B))
        {
            B& aBClass = dynamic_cast<B&>(*curObjects);
            aBClass.myUniqueFunc();
        }
            
        if (typeid(curObjects) == typeid(C))
        {
            // downcast to the derived classes to get the unique functions
            C& aCClass = dynamic_cast<C&>(*curObjects);
            aCClass.myUniqueFunc();
        }
        
    }

    return 0;
}
h4cxqtbf

h4cxqtbf1#

dynamic_cast允许转换到同级,例如:

struct IFoo
{
   virtual ~IFoo() = default;
   virtual void foo() = 0;
};

struct IBar
{
   virtual ~IBar() = default;
   virtual void bar() = 0;
   void fooBar() {
       if (auto* foo = dynamic_cast<IFoo*>(this)) {
           foo->foo();
       }
       bar();
   }
};

struct D1 : IBar { /*...*/};
struct D2 : IFoo, IBar { /*...*/ };

Demo

3zwtqj6y

3zwtqj6y2#

动态强制转换在处理大量不同对象的引擎中非常流行,例如在html引擎中。
下面是一个例子:

if(auto audio = dynamic_cast<HTMLAudioElement *>(element); audio)
    audio->Play();

尽管可以将Play作为HTMLElement的虚函数添加,但有太多类型的元素都有自己的函数,最终您将得到一个巨大的HTMLElement源文件。

pgky5nke

pgky5nke3#

基类可能来自您无法更改的库。
例如,我们在工作中制作了一个CAD,但是我们的场景对象的基类来自一个我们无法控制的框架。我们的CAD是医学的,而框架与医学无关,所以我们的医学功能在那里都没有意义。
这也使你的代码更加模块化。您可以有一个模块(可能是在运行时加载的插件),它引入一个新的派生类沿着处理它的代码。很高兴能够添加/删除这个模块而不触及基类。

相关问题