How to use dynamic_cast in if statement


How to use dynamic_cast in if statement



So I've got a simple task to do. There are 3 classes derived from one base class. They're quite simple and will be provided below.
What I need to do is create a new class called PolymorphicAnimal, that'll be able to behave just as any other animal derived from the Animal base class.
To be exact, all they need to do is display the right text after method SoundOff is called. I'm guessing I need to use dynamic_cast here. My question is, what's the right syntax for using dynamic_cast as an if statement, and do all the derived classes need to have at least one virtual method as well?


PolymorphicAnimal


animal


Animal


SoundOff


dynamic_cast


dynamic_cast


if


#include "stdafx.h"
#include <iostream>
#include <string>

class Animal {
public:
virtual std::string SoundOff() = 0;
};

class Dog : public Animal {
std::string SoundOff() override { return "Woof"; }
};

class Cat : public Animal {
std::string SoundOff() override { return "Meow"; }
};

class Cow : public Animal {
std::string SoundOff() override { return "Muu"; }
};

class PolymorphicAnimal : public Animal {
std::string sound;
public:
PolymorphicAnimal(const Animal &a) {
if(std::dynamic_cast<Cat*>(a))
}
};



The line if(std::dynamic_cast... generates compiler errors:


if(std::dynamic_cast...



syntax error '<', illegal token on the right side of :: and expected an identifier


syntax error '<', illegal token on the right side of ::


expected an identifier





whats the problem with if(std::dynamic_cast<Cat*>(a))?
– stetoc
Jul 3 at 9:21


if(std::dynamic_cast<Cat*>(a))





@stetoc syntax error '<', illegal token on the right side of ::, and expected an indentifier (in the line with dynamic_cast)
– Melvin Brooks
Jul 3 at 9:27


dynamic_cast





you cannot cast object to pointer, you need to basically add & before a in your dynamic cast so you pass address of object
– stetoc
Jul 3 at 9:29


&


a





Use if(std::dynamic_cast<Cat*>(&a).
– Peter
Jul 3 at 9:44


if(std::dynamic_cast<Cat*>(&a)




4 Answers
4



In C++ you can declare a variable in the conditional of an if, which is a powerful feature that you can exploit here. So,


if


if (auto kitty = dynamic_cast<const Cat*>(&a)){
// kitty is not nullptr
}



Notes:


dynamic_cast


std::


dynamic_cast


bool





I was trying your code, and it wouldn't work, then I realized I'm missing const, and just then it worked. This is exactly what I've been looking for. Thank you!
– Melvin Brooks
Jul 3 at 9:33


const





Also, just being curios, why wouldn't it work without const
– Melvin Brooks
Jul 3 at 9:33


const





@MelvinBrooks: Out of interest, what is the syntax that didn't work?
– Bathsheba
Jul 3 at 9:38





not the const auto kitty, but const Cat
– Melvin Brooks
Jul 3 at 9:40



const auto kitty


const Cat





Ah I see, yes you need <const Cat*> in the dynamic_cast since dynamic_cast is not allowed to cast away const-ness, const_cast is required for that, with all the cautions that go along with such a cast.
– Bathsheba
Jul 3 at 9:41



<const Cat*>


dynamic_cast


dynamic_cast


const_cast



dynamic_cast is almost always a hack.


dynamic_cast



Why don't you add another virtual method to Animal, and then have Dog, Cat and Cow override it in the usual way? Or don't you control these classes?


Animal


Dog


Cat


Cow





This is a task that usually comes on my exam and carries a nice amount of points for what it is, and the professor expects as to show that we know when and how to use dynamic_cast
– Melvin Brooks
Jul 3 at 9:37


dynamic_cast





OK, well, if you have no choice... So now you know how, and the 'when' is ... 'never' :)
– Paul Sanders
Jul 3 at 9:39






͏+͏1͏͏͏͏͏͏͏͏͏͏͏͏͏ Nothing wrong with curve-ball answers if they contain excellent advice, which this one does.
– Bathsheba
Jul 3 at 9:44





@Bathsheba Thanks, I'm honoured. Curve-ball answers are a bit of a trademark of mine. Doesn't always work, but, well, you know.
– Paul Sanders
Jul 3 at 9:56



Whereas virtual methods or visitor might be more appropriated, you might use something like:


PolymorphicAnimal(const Animal &a) {
if (const auto* cat = std::dynamic_cast<const Cat*>(&a)) {
// use cat
} else if (const auto* dog = std::dynamic_cast<const Dog*>(&a)) {
// use dog
} // ...
}



It is very unclear what exactly the PolymorphicAnimal should do. Somehow you need to tell PolymorphicAnimal how to behave, right? So, I'm guessing it's more like a Factory than a derived class.



Something like this:


class PolymorphicAnimal : Animal
{
private:
Animal *animal;
public:
PolymorphicAnimal(int type)
{
if (type == Type_Cat) // Type_Cat is an enum for example
{
animal = new Cat();
}
// ...add other types here
}
std::string SoundOff()
{
return animal->SoundOff();
}
}



Normally, you shouldn't need to do if (something dynamic_cast something) in a normal program.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages