我知道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;
}
3条答案
按热度按时间h4cxqtbf1#
dynamic_cast
允许转换到同级,例如:Demo
3zwtqj6y2#
动态强制转换在处理大量不同对象的引擎中非常流行,例如在html引擎中。
下面是一个例子:
尽管可以将Play作为HTMLElement的虚函数添加,但有太多类型的元素都有自己的函数,最终您将得到一个巨大的HTMLElement源文件。
pgky5nke3#
基类可能来自您无法更改的库。
例如,我们在工作中制作了一个CAD,但是我们的场景对象的基类来自一个我们无法控制的框架。我们的CAD是医学的,而框架与医学无关,所以我们的医学功能在那里都没有意义。
这也使你的代码更加模块化。您可以有一个模块(可能是在运行时加载的插件),它引入一个新的派生类沿着处理它的代码。很高兴能够添加/删除这个模块而不触及基类。