Dynamic_cast问题:typeid对象不相等,但名称相等

dynamic_cast issues: typeid object is not equal, but name is equal

本文关键字:不相等 对象 cast 问题 typeid Dynamic      更新时间:2023-10-16

我发现dynamic_cast没有在我期望的情况下工作,并且在运行时查看对象的typeid使情况更加不清楚。我只是想从基到派生的转换,我不明白为什么它不起作用。

我有一个像这样的类结构:

class BoundaryCondition {
public:
    virtual void DoSomething() = 0;
    virtual ~BoundaryCondition() { /* * */ }
}
class ReflectingBc : BoundaryCondition {
public:
    virtual void DoSomething();
}
class MarshakBc : BoundaryCondition {
public:
    virtual void DoSomething();
    MarshakBc(double value);
    void changeValueLaterOn(double value);
private:
    double value_;
}

我(本质上)有一个std::vector<BoundaryCondition*>,它表示问题部分的边界条件。我希望能够取vector,并将其中的所有MarshakBc对象称为changeValueLaterOn。所以我有一个像

这样的循环
for (std::vector<BoundaryCondition*>::iterator bc = bcPtrs_.begin();
        bc != bcPtrs_.end(); ++bc)
{
    if (std::string(typeid(MarshakBc).name()) == std::string(typeid(**bc).name()) )
    {
        std::cerr << "SAME! ";
    }
    if (typeid(MarshakBc) != typeid(**bc))
    {
        std::cerr << "NOT SAME ";
    }
    MarshakBc* thisBc = dynamic_cast<MarshakBc*>( &( **bc ) );
    if (thisBc == NULL) {
        std::cerr << "...nothingn";
        continue;
    }
    thisBc->changeValueLaterOn( 1.23);
    std::cerr << "...set!n";
}

如果我的向量包含一个ReflectingBc*,然后一个MarshakBc*,我的输出看起来像:

NOT SAME ...nothing
SAME! NOT SAME ...nothing

我是否误解了dynamic_casttypeid ?

[实际情况比这更复杂,因为BoundaryCondition的定义与上面的代码在不同的翻译单元中,并且涉及模板等,但上面的代码非常代表我正在做的事情和我得到的结果]


更多细节

下面是我的实际例程,它在函子内部使用,LoAnisoBc是派生类,BoundaryConditionT是基类:

template<class SnTraits_T, class LoTraits_T>
void FillLoAnisoBcs<SnTraits_T, LoTraits_T>::operator() (
        const BoundaryFaceT& bf,
        BoundaryConditionT& bc)
{
    std::cerr << "Want " << typeid(LoAnisoBc).name() << "n";
    std::cerr << "Chkg " << typeid(bc).name() << "n";
    if (std::string(typeid(LoAnisoBc).name()) == std::string(typeid(bc).name()) )
    {
        std::cerr << " SAME!";
    }
    if (!(typeid(LoAnisoBc) == typeid(bc))) {
        std::cerr << "...nothingn";
    }
    // if we're not an "anisotropic BC", don't do anything
    LoAnisoBc* anisoBc = dynamic_cast<LoAnisoBc*>( &bc );
    if (anisoBc == NULL) {
        std::cerr << "...nothingn";
        return;
    }
    anisoBc->setFCoeff( fCoeff_ );
    std::cerr << "; set fCoeff = " << fCoeff_ << "n";
}

这里是输出

Want N6detLib17cellDiffusionOned28AnisotropicBoundaryConditionE
Chkg N6detLib17cellDiffusionOned27ReflectingBoundaryConditionE
NOT SAME...nothing
Want N6detLib17cellDiffusionOned28AnisotropicBoundaryConditionE
Chkg N6detLib17cellDiffusionOned28AnisotropicBoundaryConditionE
SAME! NOT SAME...nothing

所以bcPtrs_结构和边界条件在一个动态库中(所以它是Python中的一个模块),FillLoAnisoBcs的实例化在另一个动态库中。Erik认为这是一个可能的问题,我同意。

当你跨越库边界时,typeid的行为很奇怪-例如:typeid何时可以为同一类型返回不同的type_info实例?在某些情况下。特别是,在linux上,您将需要-rdynamic来确保库中的type info对象不会被删除,从而使使用库的可执行文件无法访问。

我最好的猜测:

在您看到LoAnisoBc定义的可执行文件中,存在LoAnisoBctype_info实例。在LoAnisoBc所属的库中,存在另一个type_info实例。type_infooperator==很可能实现为一个简单的指针比较。因此,当您获得静态LoAnisoBc表达式的typeid时,您获得的是可执行实例,而引用生成的是库实例—相同的名称,但不是相同的实例。