【问题标题】:c++ - converting a base class pointer to a derived class pointerc++ - 将基类指针转换为派生类指针
【发布时间】:2013-09-23 07:25:50
【问题描述】:
#include <iostream>
using namespace std;

class Base {
public:
  Base() {};
  ~Base() {};
};

template<class T>
class Derived: public Base {
  T _val;
public:
  Derived() {}
  Derived(T val): _val(val) {}
  T raw() {return _val;}
};

int main()
{
  Base * b = new Derived<int>(1);
  Derived<int> * d = b;
  cout << d->raw() << endl;
  return 0;
}

我现在有一些多态性问题,上面的代码总结了一切。我创建了一个基类指针,并将一个新的派生模板类的指针放入其中。然后我为派生模板类创建了一个新指针,我希望它具有基类指针指向的引用。即使 Base 指针 (b) 指向 Derived,该引用也不能传递给 Derived 类指针 (d),因为 there's no known conversion from Base * to Derived&lt;int&gt; *(正如编译器所说)。

那么有没有技巧或替代方法可以做到这一点?提前致谢。

【问题讨论】:

标签: c++ pointers polymorphism


【解决方案1】:

您必须将基类型更改为多态:

class Base {
public:
    Base() {};
    virtual ~Base(){};
};

要从某个超类型转换为某个派生类型,您应该使用dynamic_cast

Base *b = new Derived<int>(1);
Derived<int> *d = dynamic_cast<Derived<int> *>(b);

在此处使用dynamic_cast 检查是否可以进行类型转换。如果不需要做那个检查(因为演员不会失败),你也可以使用static_cast

Base *b = new Derived<int>(1);
Derived<int> *d = static_cast<Derived<int> *>(b);

【讨论】:

  • +1 表示 Base 需要 dynamic_cast 的虚函数
  • -1 表示您“必须”使用 dynamic_cast。你不必这样做。
  • @NeilKirk 正确,但应该使用 dynamic_cast,因为它会检查演员表是否可能。
  • @NeilKirk Visual Studio 2015 将只允许 dynamic_cast,并突出显示 static_cast 是错误的。 +1 返回
  • 为什么基类需要是多态的?
【解决方案2】:

试试这个:

Derived<int> * d = static_cast<Derived<int>* >(b);

缺点是,您可以转换作为 Base() 实例的类,然后 d->raw() 将是未定义的(分段错误可能)。如果是这种情况,请使用 dynamic_cast 并至少拥有一个基于虚拟的函数(在使用多态时,具有虚拟的析构函数是必不可少的)。

虚拟函数是使用虚拟表上的指针实现的。该指针也可用于识别类的真实类型。 dynamic_cast 使用它来检查是否可以完成此转换,并在转换时带来少量额外开销。

【讨论】:

    【解决方案3】:

    你可以使用 dynamic_cast

    Derived<int> * d = dynamic_cast<Derived<int> *>(b);
    

    如果转换失败(基指针未指向请求的派生类型),则返回 null。

    但是,要使 dynamic_cast 起作用,您的基类必须至少具有一个虚函数。我建议您将析构函数设为虚拟(这也可以防止删除对象时出现其他潜在问题)。

    使用 dynamic_cast 可能表明您的代码设计不佳。

    请注意,如果您 100% 确定基指针指向您的派生类型,那么您可以将其替换为 static_cast,这会稍微快一些。一般来说,我个人更喜欢额外的安全检查。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-31
      • 2014-03-09
      • 1970-01-01
      • 2021-09-09
      相关资源
      最近更新 更多