dynamic_cast的继承和使用 [英] Inheritence and usage of dynamic_cast

查看:123
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆