在运行时如何确定非多态类型的实际类型

时间:2014-05-07 14:48:53

标签: c++

我有这样的声明:

struct InstrumentInfo
{
    std::string Name;
    TradingStatus Status;
    myDecimal MinStep;
    std::string ISIN;
    myDecimal limit_down;
    myDecimal limit_up;
};

struct FortsDerivativeInfo : InstrumentInfo
{
    std::string ShortIsin;
    int IsinId;
    std::string CodeVcb;
    myDecimal StepPrice;
    int LotVolume;
    myDecimal exch_pay;
};

struct StockInfo : InstrumentInfo
{
    int LotSize;
};

我试图编写这样的代码:

if (auto si = dynamic_cast<StockInfo*>(ii))
{
    LOT_SIZE = si->LotSize;
}
else
{
    LOT_SIZE = 1;
}

这不编译,我收到“错误C2683:'dynamic_cast':'InstrumentInfo'不是多态类型”。我该如何解决这个错误?

如果我将dynamic_cast替换为static_cast代码编译,但由于static_cast不执行任何运行时检查,我担心这不起作用?

3 个答案:

答案 0 :(得分:2)

运行时类型信息仅适用于具有至少一个虚函数的类型(即&#34;多态类型&#34;)。使dynamic_cast工作的唯一方法是使基本类型具有多态性 - 例如,通过声明其析构函数virtual

更好的方法是完全取消对强制转换的需求 - 例如,通过创建虚拟lotSize函数:

struct InstrumentInfo
{
    std::string Name;
    TradingStatus Status;
    myDecimal MinStep;
    std::string ISIN;
    myDecimal limit_down;
    myDecimal limit_up;
    virtual int lotSize() const { return 1; }
};

struct StockInfo : InstrumentInfo
{
    int LotSize;
    virtual int lotSize() const { return LotSize; }
};

InstrumentInfo ii;
LOT_SIZE = ii.lotSize();

答案 1 :(得分:0)

非多态类型(没有虚函数的类型)没有运行时类型信息。

InstrumentInfo中添加虚拟析构函数将为您提供RTTI并使dynamic_cast正常工作,但解决问题的更好方法是,如另一个答案中所指出的,使用虚拟成员函数返回批量大小。不管RTTI如何使用虚拟析构函数都是个好主意,否则如果你这样做会有一些严重的问题:

InstrumentInfo * info = new FortsDerivativeInfo;
delete info;

这会导致未定义的行为(通过没有虚析构函数的基类指针删除派生对象)。

答案 2 :(得分:0)

简短的回答是:dynamic_cast仅适用于多态类型,因此您必须寻找替代方案。


更长的答案是你有其他选择:

  • 最简单的是添加一个virtual方法(基类的析构函数),你的代码将按原样编译
  • 但一般情况下,如果您可以使用virtual方法,请创建一个可以避免这种丑陋演员的方法
  • 存在其他替代方案,例如在基类中具有enum,其指示当前实例化哪个子项;它们不是自动化的,因此是最后的追索权