6 ms·
I can't think of a dynamic_cast scenario I've seen that was not indicative if an improper class design; typically that the base class doesn't have proper virtua
by CoolGuySteve 7y ago
I can't think of a dynamic_cast scenario I've seen that was not indicative if an improper class design; typically that the base class doesn't have proper virtual methods defined, or there's a missing ABC interface, or the inheritance is just inappropriate.
It's also brutally slow in most compilers.
After that consideration, C-casts are mostly fine. static_cast/reinterpret_cast are more explicit but the syntax is bizarrely verbose.
But I'm way more annoyed by dynamic_cast than C-casts whenever it they come up.
- epx 7y agoAnd it does not work when RTTI is absent. Had this problem in embedded development a couple days ago. Changed to static_cast, then refactored to avoid casting.
- kccqzy 7y agoI've only used dynamic_cast in unit tests, to verify that a base class pointer is indeed of a certain subclass.
- scott_s 7y agoC-style casts in C++ are a sledgehammer. You will get an object of the cast type afterwards, but it may not happen the way you thought it would. That's why it's better to use the C++ casting constructs. If you try, say, a static_cast, and that's not possible, the compiler will tell you that in an error message. Then you're forced to reason through why it's not possible, and what you need to do about it.
- klodolph 7y agoCounterpoint… it’s a bit verbose when you need to cast for bitwise operations. uint32_t packed = ((uint32_t)x << 16) | ((uint32_t)y & 0xffff); uint32_t packed = (static_cast<uint32_t>(x) << 16) | (static_cast<uint32_t>(y) & 0xffff); The verbosity of static_cast can get out of hand, and make it harder to read.
- deleted 7y ago[deleted]
- gok 7y agoIt can be useful when used for interface-style pure virtual inheritance.
- deleted 7y ago[deleted]
- MauranKilom 7y agoWhat do you think of the following: class AInterface { /*...*/ }; class BInterface : public AInterface { /*...*/ }; class CInterface : public BInterface { /*...*/ }; class AImpl : public AInterface { /*...*/ }; class BImpl : public BInterface { /*...*/ }; class CImpl : public CInterface { /*...*/ }; In this use case, assume going from AInterface to CInterface implies stronger and stronger guarantees that the implementations provide. Also assume LSP as satisfied. Now, you are given an AInterface* object and want to know whether it has a certain guarantee or not. A dynamic cast answers this with minimal space overhead. Yes, there is certainly run time overhead in the dynamic cast, and you could just have a virtual method that returns some encoding of the guarantees (e.g. as an enum), but the dynamic_cast is still pareto-optimal in terms of space. Change my mind?
- brandmeyer 7y ago> Now, you are given an AInterface* object and want to know whether it has a certain guarantee or not. Eiffel guarantees this in the LSP sense, by enforcing that overrides `require` as much or less than their base class, and `ensure` as much or more than their base class. If you want to query that from AInterface alone, you should expose a virtual member that allows you to make the specific inquiry of interest from AInterface. In effect, if users of AInterface must know that only some AInterface's meet some guarantee, you must expose some knowledge of the guarantee in AInterface itself. For example, AInterface can expose a boolean predicates like supports_foo, or it can return an object that is comparable with a std::strong_ordering.
- MauranKilom 7y agoI fully agree, this is what I would go for in this case. The only caveat is that this is duplicating information that RTTI already has available, i.e. space overhead. That's not a strong argument, but still a pareto-optimal niche.
- jfkebwjsbx 7y agoGiven most people use C++ for its performance in time rather than in space, I think most projects would go with a member/virtual method.