Today I ran into problems using dynamic_cast with a custom class - API class - for which I got the following error:
Severity Code Descript'dynamic_cast' used on polymorphic type 'Condition' with /GR-; unpredictable behavior may result
Which makes perfect sense. Question is, how can I enable it?
I should see something like that on project proprieties, but I don’t, for some reason, I never do in UE4 projects.
UE4 disables C++ RTTI for a number of reasons. However, the main one is that UE4 builds its own RTTI and using built in RTTI would be quite wasteful. Furthermore, it could cause unknown errors as I doubt it has been tried.
Instead of doing a dynamic cast, just use a plain C-style cast or Epic’s own Cast template function.
It’s not always a good idea to make everything a UObject though. The extra functionality that UObject provides comes with extra overhead, and this results in UObject not being a good base class for small, short-lived objects for example.
Presumably there is a type-hierarchy being used here, else dynamic_cast wouldn’t work, so you’ll need to provide a type property to identify the class type in place of RTTI.
Yep, you’ll either need to store some type information yourself, or probably better, just redesign so that it’s not necessary.
Generally use of dynamic_cast can be replaced by use of polymorphism (virtual functions). Your code will likely end up much cleaner if you don’t need to check at runtime if an object is of a particular derived type, but just invoke a virtual function on it instead.
Sorry for the late reply, here’s how the code is at the moment - because it has one pure virtual function:
class Game_API Base
{
public:
....
virtual bool TestImpl(.....) = 0;
then I have several classes which implement Base,e.g.
class Game_API A : public Base
class Game_API B : public Base
class Game_API C : public Base
Finally, inside class A I have a method ,e.g.
void A::JustAMethod(Base* obj)
{
....
And now I want to see if obj is an instance of A,B or C - it cannot be of instance Base since it has pure virtual functions. And this is when I get the error, when I try to castobj to A.
Without knowing what your code is trying to do or why, a simple and easy solution to this would be to create an enum with a value mapping to each of your class types. Then, add a virtual function to your base class that’s something like GetClassType. Then, in each of the child classes, have them implement that function and return their corresponding enum.
You could also accomplish this without the enum by using individual functions i.e IsClassA(), IsClassB(), etc. This can make your code messy very quickly, but it’s also more flexible. For instance, you could support ClassC which is a child of ClassB which is a child of ClassA, and you would be able to call IsClassA(), IsClassB(), and IsClassC() and they would all return true.
Yes I had considered the first option - the second one, for practical and good-standard programming reasons, I haven’t considered it - but, its not that practical nor makes sense having to resort to such options. I mean, this is exactly what casting is for, I can’t quite understand why it isn’t working when I have polyphormism (at least one pure virtual method is in the base class).
If it’s just an isolated situation then the first option will work, but it’s not ideal, it isn’t scalable at all.
With polymorphism though, the whole idea is that you don’t need to ask what type of object you’re dealing with. You just invoke a virtual function, and the various implementations will do whatever they need to do. In some cases, for some classes that may be nothing at all. You haven’t said what you’re trying to achieve on a higher level though, so it’s hard to say how you should go about it.
Dynamic casting is slooooooooow. That’s why pretty much every professional engine implements their own version. Vtable lookups also have a cost, but the hit is small and usually only matters in places where performance is critical.
The common pattern for implementing custom RTTI is how Unreal does it. They have macros for writing a bunch of the boilerplate code, with functions that are comparing class IDs that are generated based on the class name. You can take a look at cast.h if you’d like to see it in action.
Well I know its slow, but tbh the code will be executed only once - when the game loads - and only a few times over, so its not that problematic I guess, although better performance solutions would be better
As for the custom RTII…way beyond my knowledge lol
This solution is something you want to show to your students and tell them to never ever use it in their code. There are better solutions both: clean-code-wise and performance-wise:
It was probably Ok to use enum solution in some language in 1972 when there simply was no alternatives in your language back then. It is not Ok to use it in modern languages: in C++ case it’s since the moment it was introduced in 1979.
This one has all the problems the first one has. Instead of a switch statement you have a bunch of if statements everywhere your code uses this hierarchy.
Sorry for the bump — came across this thread because I had a use-case for RTTI in a non-UClass type. I came up with what I think is a pretty lightweight solution (though I would definitely be open to constructive criticism), so I thought I would share in case it’s useful to anyone in the future.
First an overview of the use case:
I have a custom Slate widget for viewing trees. These trees are basically collections of some type (the leaf nodes) which are grouped into nested categories. The desired behavior is that when any given category is selected in the tree-view, all of the leaf-node items that are descendants of that category node are recursively coalesced into a flat array for viewing in a separate list-view.
I wanted these “category trees” to be usable for different types of leaf nodes, but I didn’t want to have to hard-code all of the valid leaf-node types up front (e.g., by using an enum for the type ID), as this is part of an editor plugin, and I think it would be useful if different projects using the plugin could specify their own leaf-node types. But I also didn’t want to have to redefine the function that coalesces the leaf-nodes for every leaf-node type. I wanted to define a template function that would work for any T that derives from my base node class.
This is what I came up with (requires C++20 as-written, though you could probably refactor it to use an SFINAE / TEnableIf pattern if you needed to):
This works because FNodeTypeRegistry::GetTypeID<T>() is compiled once for each T it’s invoked with, and since its return value is declared with static storage, it will only increment LastUsedTypeID the first time it’s invoked for any given T — all subsequent invocations will return that same initial value.
With this infrastructure in place, you can do type-checking in a template function like this: