35
#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;
}

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

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

4

3 回答 3

61

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

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);
于 2013-09-18T13:49:30.177 回答
3

试试这个:

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

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

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

于 2013-09-18T14:01:21.457 回答
2

您可以使用 dynamic_cast

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

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

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

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

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

于 2013-09-18T13:51:05.980 回答