c ++ - 将基类指针转换为派生类指针

And*_*ida 22 c++ polymorphism pointers

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

那么有没有一种技巧或另一种方法可以做到这一点?提前致谢.

Abr*_*as2 42

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

class Base {
public:
    Base() {};
    virtual ~Base(){};
};
Run Code Online (Sandbox Code Playgroud)

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

Base *b = new Derived<int>(1);
Derived<int> *d = dynamic_cast<Derived<int> *>(b);
Run Code Online (Sandbox Code Playgroud)

dynamic_cast在这里使用检查可以进行类型转换.如果没有必要进行检查(因为演员表不能失败),你也可以使用static_cast:

Base *b = new Derived<int>(1);
Derived<int> *d = static_cast<Derived<int> *>(b);
Run Code Online (Sandbox Code Playgroud)

  • +1注意Base需要dynamic_cast的虚函数 (4认同)
  • -1表示你“必须”使用dynamic_cast。你不必这样做。 (2认同)

Nei*_*irk 6

您可以使用dynamic_cast

Derived<int> * d = dynamic_cast<Derived<int> *>(b);
Run Code Online (Sandbox Code Playgroud)

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

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

使用dynamic_cast可能表明代码中的设计不好。

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


Luk*_*hne 5

尝试这个:

Derived<int> * d = static_cast<Derived<int>* >(b);
Run Code Online (Sandbox Code Playgroud)

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

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