Dynamic_cast problems: typeid object is not equal, but name is equal

I found that dynamic_cast did not work in a situation where I was expecting this, and looking at typeid objects at runtime made the situation even less clear. I just want the cast from the base to be received, and I cannot understand why it is not working.

I have a class structure like this:

 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_; } 

I (essentially) a std::vector<BoundaryCondition*> , which represents the boundary conditions in the parts of the problem. I want to have this vector and for all MarshakBc objects inside it call changeValueLaterOn . So I have a loop that looks like

 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 << "...nothing\n"; continue; } thisBc->changeValueLaterOn( 1.23); std::cerr << "...set!\n"; } 

If my vector has ReflectingBc* , then a MarshakBc* , my output looks like this:

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

Am I misunderstanding something about dynamic_cast and typeid ?

[The actual situation is more complicated than this because the BoundaryCondition definition is in a different translation unit than the code above and the templates are used, etc., but the code above is very representative of what I do and the result I get .]


More details

Here is my actual procedure, which is used inside a functor, and LoAnisoBc is a derived class, and BoundaryConditionT is a base class:

 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 << "...nothing\n"; } // if we're not an "anisotropic BC", don't do anything LoAnisoBc* anisoBc = dynamic_cast<LoAnisoBc*>( &bc ); if (anisoBc == NULL) { std::cerr << "...nothing\n"; return; } anisoBc->setFCoeff( fCoeff_ ); std::cerr << "; set fCoeff = " << fCoeff_ << "\n"; } 

And here is the conclusion

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

So, the bcPtrs_ structure and the boundary conditions are in one dynamic library (so this is one module in Python), and the FillLoAnisoBcs instance is in another dynamic library. Eric considers this a probable problem, and I agree.

+6
source share
1 answer

typeid behaves strangely when you cross the boundaries of libraries - see, for example, When does typeid return different instances of type_info for the same type? for some cases. In particular, for linux, you will need -rdynamic so that type information objects from the library are not deleted and therefore are not accessible to the executable using the library.

My best guess:

In the executable, where you see the definition of LoAnisoBc , there is an instance of type_info for LoAnisoBc . In the library where LoAnisoBc "belongs", there is another instance of type_info . type_info operator== most likely implemented as a simple pointer comparison. So, when you get the typeid of the LoAnisoBc static expression, you get an executable instance, while the link creates an instance of the library - the same name, but not the same instance.

+1
source

Source: https://habr.com/ru/post/885839/


All Articles