Alternatives to dynamic_cast

Started by
13 comments, last by Hodgman 8 years, 4 months ago
I try to solve problems without polymorphism when possible. In your case, a person could be both a student and an employee, since that is the case I would not use polymorphism here, use composition instead.



class Person {

}

class Employee {
public:
  Person* GetPerson();
private:
  Person *person;
}

class Student {
public:
  Person* GetPerson();
private:
  Person *person;
}

My current game project Platform RPG
Advertisement


A dynamic cast can be easily converted to a virtual function. For every "dynamic_cast<X*>", make a virtual function "X* GetX()", which returns "nullptr" in the base class, and "this" in the X class, eg (leaving out the declarations, constructors, etc).

This could work if all possible implementations of the class are known at compile / link time, but this is not the case in general.

A dynamic cast can be easily converted to a virtual function. For every "dynamic_cast<X*>", make a virtual function "X* GetX()", which returns "nullptr" in the base class, and "this" in the X class, eg (leaving out the declarations, constructors, etc).


class A {
    virtual B* GetB() { return nullptr; };
    virtual C* GetC() { return nullptr; };
};

class B : public A {
    virtual B* GetB() { return this; };
};

class C : public A {
    virtual C* GetC() { return this; };
};
Of course, the idea hasn't improved at all even if you code it in virtual functions.

For the above reason, I don't think dynamic_cast would be extremely expensive compared to virtual functions. A compiler could add this kind of code.



@Matias Goldberg

if( basePtr->getType() = DERIVED_TYPE )
That should be 2 '=' signs there smile.png


This approach requires that you forward declare all the derived classes before you define the interface for the base class, which is a very different situation to dynamic_cast, which only requires the derived classes to be known at runtime and not known to the base class implementation.

Im going to go ahead and throw my neck out to the knives and say that I disagree and feel that the general guiding principles of c++ carry to much weight in matters like this. In this case specifically, we don't know the role of the consumer at this point or its intended future use.

-Claiming this scenario is better suited for a composition approach breaks one of the very first things you learn about composition and inheritance. A person is not composed of a student or an employee. If composition were considered than you might as well throw out the Person class and add new objects called EmployeeBadge and Backback for the Employee and Student objects to use respectively. This would completely change the architecture of the program at this point.

-We don't know the role of the consuming object that holds the Person list. Creating virtual functions to inherit from to complete a task may work when the Employee or Student have specific tasks that the consumer is delegating, but what if the consumer needs information from those classes to perform a job that the Student or Employee have no knowledge of(and should not). What if the consumer is the school that the Student attends and the Employee work at? The school needs to get information from these two separate classes to file a tax return to the Government(or what ever arbitrary example you want to use).

I feel there is nothing wrong with casting as long as it fits the concept as it helps to better follow and maintain code.

That's my 2 cents

Edit: What if you want to keep expanding on the Person list and add a SecurityPersonnel object to the list? Or further go down and start subclassing Employee into Teacher, GymTeacher ect... In this case, inheritance sounds like the logical thing to do here.

A person is not composed of a student or an employee

No, A student and an employee are composed of a person. A student instance and an employee instance might share the same person.

Claiming this scenario is better suited for a composition approach breaks one of the very first things you learn about composition and inheritance.

The first rule of inheritance is: prefer using composition by default, and use inheritance only when necessary.

Creating virtual functions to inherit from to complete a task may work when the Employee or Student have specific tasks that the consumer is delegating, but what if the consumer needs information from those classes to perform a job that the Student or Employee have no knowledge of(and should not). What if the consumer is the school that the Student attends and the Employee work at? The school needs to get information from these two separate classes to file a tax return to the Government(or what ever arbitrary example you want to use).

If the algorithm has to change it's behaviour depending on the specific derived type hiding behind the common interface, then that is a sign that the Liskov substitution principle has been violated, so inheritance was not a valid choice in the first place. That is not a valid OO design.

What if you want to keep expanding on the Person list and add a SecurityPersonnel object to the list? Or further go down and start subclassing Employee into Teacher, GymTeacher ect... In this case, inheritance sounds like the logical thing to do here.

No, as above, it breaks the rules of OOD and is unecessary. Also, what do you do when a student gains a job as a lecturer, while still studying? Do you delete their Student instance and replace it with a StudentAndEmployee instance that makes use of multiple inheritance?
This example is the text book example of inheritance abuse...

This topic is closed to new replies.

Advertisement