dynamic_cast的继承和使用 [英] Inheritence and usage of dynamic_cast
问题描述
假设我有3个类如下(因为这是一个例子,它不会编译!):
Suppose I have 3 classes as follows (as this is an example, it will not compile!):
class Base
{
public:
Base(){}
virtual ~Base(){}
virtual void DoSomething() = 0;
virtual void DoSomethingElse() = 0;
};
class Derived1
{
public:
Derived1(){}
virtual ~Derived1(){}
virtual void DoSomething(){ ... }
virtual void DoSomethingElse(){ ... }
virtual void SpecialD1DoSomething{ ... }
};
class Derived2
{
public:
Derived2(){}
virtual ~Derived2(){}
virtual void DoSomething(){ ... }
virtual void DoSomethingElse(){ ... }
virtual void SpecialD2DoSomething{ ... }
};
我想创建Derived1或Derived2的实例,这取决于一些设置,
I want to create an instance of Derived1 or Derived2 depending on some setting that is not available until run-time.
由于我无法确定派生类型直到运行时,那么你认为以下是不好的做法?...
As I cannot determine the derived type until run-time, then do you think the following is bad practice?...
class X
{
public:
....
void GetConfigurationValue()
{
....
// Get configuration setting, I need a "Derived1"
b = new Derived1();
// Now I want to call the special DoSomething for Derived1
(dynamic_cast<Derived1*>(b))->SpecialD1DoSomething();
}
private:
Base* b;
};
我一般认为dynamic_cast的用法不好,但正如我所说,
在运行时之前创建的类型。请帮助!
I have generally read that usage of dynamic_cast is bad, but as I said, I don't know which type to create until run-time. Please help!
推荐答案
使用dynamic_cast本身并不糟糕。这是不好的做法,使用它不适当,即在那里它不是真正需要。
Using dynamic_cast is not bad practice per se. It's bad practice to use it inappropriately, i.e. where it's not really needed.
以这种方式使用它也是一个坏习惯:
It's also a bad practice to use it this way:
(dynamic_cast<Derived1*>(b))->SpecialD1DoSomething();
原因:dynamic_cast(b)可能会返回NULL。
Reason: dynamic_cast(b) may return NULL.
当使用dynamic_cast时,你必须格外小心,因为它不能保证,b实际上是Derived1而不是Derived2:
When using dynamic_cast, you have to be extra careful, because it's not guaranteed, that b is actually of type Derived1 and not Derived2:
void GenericFunction(Base* p)
{
(dynamic_cast<Derived1*>(b))->SpecialD1DoSomething();
}
void InitiallyImplementedFunction()
{
Derived1 d1;
GenericFunction(&d1); // OK... But not for long.
// Especially, if implementation of GenericFunction is in another library
// with not source code available to even see its implementation
// -- just headers
}
void SomeOtherFunctionProbablyInAnotherUnitOfCompilation()
{
Derived2 d2;
GenericFunction(&d2); // oops!
}
您必须检查dynamic_cast是否确实成功。有两种方法:在投放之前和之后检查它。在转换之前,您可以检查您要转换的指针是否实际上是您通过RTTI预期的指针:
You have to check if dynamic_cast is actually successful. There are two ways of doing it: checking it before and after the cast. Before the cast you can check if the pointer you're trying to cast is actually the one you expect via RTTI:
if (typeid(b) == typeid(Derived1*))
{
// in this case it's safe to call the function right
// away without additional checks
dynamic_cast<Derived1*>(b)->SpecialD1DoSomething();
}
else
{
// do something else, like try to cast to Derived2 and then call
// Derived2::SpecialD2DoSomething() in a similar fashion
}
事后检查它实际上有点简单:
Checking it post-factum is actually a bit simpler:
Derived1* d1 = dynamic_cast<Derived1*>(b);
if (d1 != NULL)
{
d1->SpecialD1DoSomething();
}
我也认为这是一个糟糕的做法,在C ++中。 C ++中有许多功能似乎是完全没有打字更短(即让你觉得NULL将永远不会发生在这里),但结果是一个痛苦的屁股调试后。 ;)
I'd also say it's a bad practice to try and save typing while programming in C++. There are many features in C++ than seem to be completely fine to be typed shorter (i.e. makes you feel 'that NULL will never happen here'), but turn out to be a pain in the ass to debug afterwards. ;)
这篇关于dynamic_cast的继承和使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!