Casting from base class to derived class

Hello!

I'm stuck with a problem related to class casting. Suppose we have these classes:

class Screen
{
   void initialize(void);
}

class HelloScreen : public Screen
{
   void initialize(void);
   void hello(void);
}

In other part of my code, I'm trying to do somthing like this:

Screen* scrCurrent;
...
((HelloScreen)scrCurrent)->hello();

The last line containing he cast is generating an error and I cannot find a solution for that. Of course, I'm trying to invoke the hello() method when I know that the scrCurrent instance is of type HelloScreen.

Surely it is nonsense, but I cannot find a solution... can you help me?

THANKS in advance! :sweat_smile:

It’s a pointer to an instance of the class, so need the star

Screen* scrCurrent;
...
((HelloScreen*)scrCurrent)->hello();

May be you want a virtual in the root class

1 Like

First of all, your initialize function should probably marked virtual in your base class and override in your derived classes.
Also leave out the (void) in your function declarations, if there are no parameters, just use ().

The safe way to perform this down-cast is using dynamic_cast. This only works on boards with RTTI enabled (and you need at least one virtual member).

If that's not an option, you'll have to use an unsafe static_cast:

static_cast<HelloScreen *>(scrCurrent)->hello();

Pieter

1 Like

Thanks!! :+1:

That’s not bad practice, it’s part of the spec and this shows the deceloper’s intent. Some companies would insist you have it as internal rules,

(It’s origin is more in C though)

1 Like

Yes, of course, I'm using virtual methods in my base class, I omitted them for simplicity in the sample code (thanks for the suggestion). And, related to the cast, this solution is better than the solution proposed by J-M-L?

Yes it’s cleaner and safer with the dynamic_cast (although throwing exception is not supported in small arduinos)

1 Like

I will apply this solution.
Many thanks to both! :ok_hand:

I would argue that there is no difference in intent, an empty argument list clearly shows that you don't want any arguments, adding a redundant void doesn't help.

When I see code with (void) all over the place, I assume the author is familiar with C, but might not be very experienced in C++.

For what it's worth, the C++ Core Guidelines explicitly advise against it: C++ Core Guidelines

1 Like

When applying dynamic_cast to a pointer, it will return nullptr if the cast was invalid, it doesn't throw an exception. You still have to check for null, of course.

dynamic_cast is safer, but it has some overhead. static_cast has no overhead, but it's extremely easy to shoot yourself in the foot with it.

I would definitely advise you to use static_cast<HelloScreen *>(scrCurrent) over a C-style cast (HelloScreen *) srcCurrent. C-style casts will automatically be converted to a reinterpret_cast or even a const_cast when a static_cast is impossible. You absolutely don't want that here. If the compiler doesn't think static_cast is valid, there's something wrong with your code, and you want a compiler error, not silently falling back to even unsafer casts that will cause undefined behavior at runtime.

1 Like

Yes in cas of a pointer there is no throw. My answer was meant to be generic.

Agreed on void, I’ve just seen it in some companies to explicitly show you had willfully designed this function without any parameter. Probably inherited from past C coding rules that nobody challenged or for libraries that are meant to be used both in C and C++ maybe

Thanks for the link on C++ Core Guidelines, I did not know they were explicitly advising against that

Most likely :smile:

For the record, do use void in empty argument lists in C functions, but not in C++.

It's just a guideline of course, there might be cases where you want to deviate from it, e.g. in code bases where C and C++ code is mixed all the time.
In general though, I think the Core Guidelines are quite sensible, and it's valuable to follow them, towards a cleaner and often safer coding style that the majority of developers can agree on.

You could... Depending on your design. Add.

class Screen
{
   void initialize(void);
   virtual void hello(void); 
}

Add a do nothing hello() method to your base class. That way the method will always be there and safe to call. I realise in many code designs this is just not a very good idea. Just an option if it works.

Another is to add some sort of method in your base class that passed back an ID. Then the derived classes can set that ID to show you if its a safe call or not.

-jim lee

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.