我正在阅读一些关于 dynamic_cast 的 C++ 材料,以下做法被认为是不好的:
class base{};
class derived1 d1 :public base{};
class derived2 d2 :public base
{
public:
void foo(){}
};
void baz(base *b)
{
if (derived2 *d2= dynamic_cast<derived2 *> (b) )
{
d2-> foo();
}
}
对此的补救措施是使用空的纯虚拟基类来使用“能力查询”,如下所示:
class capability_query
{
public:
virtual void foo()= 0;
};
class base{};
class derived1 d1 :public base{};
class derived2 d2 :public base, public capability_query
{
public:
virtual void foo(){}
};
void baz(base *b)
{
if (capability_query *cq= dynamic_cast<capability_query *> (b) )
{
cq-> foo();
}
}
我的第一个问题是为什么第一个代码块被认为是坏的?我看到它的方式foo
只有在 d2 可以从baz
函数中的 b 成功向下转换时才会执行。那么这里的问题是什么?!
我的第二个问题是为什么第二个代码块被认为是好的?以及这如何解决这个问题,我首先不明白。
仅供参考,我的谷歌搜索capability query
返回的http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Capability_Query
似乎基本上是代码块 1 而不是代码块 2。我仍然不明白为什么额外的空基类被认为是更好的做法?
编辑:
这是我能想到的最好的答案。因为在里面baz
我向下转换为指针类型而不是引用,如果向下转换不成功,我将得到一个空指针而不是 std::bad_cast。所以,假设转换出错并且我确实得到了 NULL 指针,但是如果我不应该执行Null->foo
并且如果我可能忘记测试 NULL 怎么办,那么代码块 1 可能是一个问题。代码块 2 解决此问题的方法是添加一个空类。即使
dynamic_cast<capability_query *> (b)
失败,我得到一个空指针,你不能执行,
null->foo
因为在capability_query
类内部这个foo
方法是纯虚拟的。这只是一个猜想,但也许我走在正确的道路上??!!