c++ – Cast-order for inherited classes? – Education Career Blog

I’ve got 3 classes:

class Super
{
    virtual int getType() { return 1; }
}
class Special : public class Super
{
    virtual int getType() { return 2; }
}
class SpecialSpecial : public class Special
{
    virtual int getType() { return 3; }
}

And I’ve got a function which takes an std::vector<Super*> as argument:

void handleClasses( std::vector<Super*> superVector )
{
    foreach element in superVector //Pseudocode!!
    {
        if( element->getType() == 1 )
            std::cout << "Thats a SuperClass" << std::endl;
        else if( element->getType() == 2 )
            std::cout << "Thats a SpecialClass" << std::endl;
        else if( element->getType() == 3 )
            std::cout << "Thats a SpecialSpecialClass" << std::endl;
    }
}

There could be a User which inherits from class Special:

class ParalellSpecial : public class Special
{
    virtual int getType() { return 4; }
}

Now the function handleClasses is not able to understand the new class with type 4, but it should be able to use the next superior class (in this case it is Special).

How would someone implement such a thing? Is there a design pattern which allows to create an hierarchical order of classes and the next available superclass will be used as a fallback, if the current class could not be used (cause it is unknown)?

NOTE: The Type-Identifiers are just for demonstration-purposes. There surely are better methods to identify a classtype in C++ (RTTI).

,

2 possible answers here:

1) If you think you need to know what type an object really is, then maybe your encapsulation is wrong. Perhaps handleClasses() should be calling a method on the object, and each class should provide a different implementation?

2) If this is one of the rare times when you really need to know the type of an object, use dynamic_cast<>. That’s what it’s for. E.g:

void handleClasses( std::vector<Super*> superVector )
{
    foreach element in superVector //Pseudocode!!
    {
        if( dynamic_cast<SpecialSpecial *>(element) != 0 )
            // SpecialSpecial or a subclass of SpecialSpecial 
            std::cout << "Thats a SpecialSpecialClass" << std::endl;
        else if( dynamic_cast<Special *>(element) != 0 )
            // Special or a subclass of Special
            std::cout << "Thats a SpecialClass" << std::endl;
        else
            // Super or a subclass of Super
            std::cout << "Thats a SuperClass" << std::endl;
    }
}

,

A first solution to get the thing moving:

The child-classes integrate the type of the superclasses into their own Type-ID.
Super gets Type == 1
Special gets Type == 21
SpecialSpecial gets Type == 321
ParalellSpecial gets Type == 421

The handleClasses now checks if the first digit is known (which is not the case for ParalellSpecial. Then it checks if the second digit is known (which is the case) and then prints the related message (or does whatever it wants to do, e.g. casting from Super to Special)

This concept has the big disadvantage that there could only be 10 classes per hierarchy-level. Also the concept of Type-Identifiers isn’t optimal I think.

Think there are better solutions available.

,

It really depends on your actual problem. Usually, if you have special cases for every of your classes that you cannot cover using polymorphism, then inheritance is probably not a good solution to your problem.

Another idea would be to create a global type registry that knows about the relationships of the types. You could then use the registry to move through the hierarchy until you find a type that you can handle. The registry could just be a DAG with the type-ids as nodes.

Leave a Comment