#include <iostream>
#include <string>
#include <vector>
class Animal{};
class Person: public Animal
{
public:
std::string name = "Michael Scott";
};
class Bird: public Animal {};
int main()
{
auto animal = new Animal;
auto person = new Person;
auto bird = new Bird;
std::vector<Animal*> creatures {animal, person, bird};
for (auto c: creatures)
{
std::cout << c << std::endl;
/*
if c has the attribute "name", do what ever
*/
}
return 0;
}
In python it would as simple as writing hasAttr(c, "name"), but I have been researching how to do it in C++ and I didn't find a clear answer for this.
Hello. Maybe it's not the answer which you expected, but if you want to check if a class has a derived-type object, you can use is_base_of. It could be useful for you instead of searching for a hypothetical member. If the resut is false, you have no member acces to the derived class... Just an idea ++
PS : but in your example, only Person class has acces to the name member :/
#include <iostream>
#include <string>
#include <vector>
class Animal
{
public:
virtual ~Animal() = default;
};
class Person: public Animal
{
public:
std::string name = "Michael Scott";
};
class Bird: public Animal {};
int main()
{
auto animal = new Animal;
auto person = new Person;
auto bird = new Bird;
std::vector<Animal*> creatures {animal, person, bird};
for (auto c: creatures)
{
std::cout << c << std::endl;
if ( auto p = dynamic_cast<Person*>( c ) )
{
std::cout << p->name << '\n';
}
}
for (auto c: creatures) delete c;
}
However, much more common is to have common interface on the base class that the derived classes can embellish:
#include <iostream>
#include <vector>
class Animal
{
public: // required ??? without it code does not compile
virtual ~Animal() = default;
};
class Person : publicvirtual Animal
{
public:
std::string name = "Michael Scott";
};
class Bird : publicvirtual Animal {};
int main()
{
auto animal = new Animal;
auto person = new Person;
auto bird = new Bird;
std::vector<Animal*> creatures{ animal, person, bird };
for (auto c : creatures)
{
if (auto p = dynamic_cast<Person*>(c))
{
std::cout << p->name << std::endl;
p->name = "Another name"; // change it for test
std::cout << p->name << std::endl;
}
}
}
In python it would as simple as writing hasAttr(c, "name"), but I have been researching how to do it in C++ and I didn't find a clear answer for this.
There isn't really anything equivalent because the languages are so different. In C++ we would normally try to solve it some other way.
One way would be to let every Animal have a name that might be empty or null to signal that there is no name. keskiverto have shown one variation of this. If you don't want to use inheritance you could just use a name string member variable, and possibly an enum to signal what type of animal it is.
I doubt reflection is the right answer here. Mainly since this is the beginners section and reflection will be more of an expert tool and it's not even standardized yet. But also because I don't see how you would use it in this situation. I mean, you wouldn't be able to extract information from an Animal* that is only available in one of its derived classes unless you cast the pointer to that type first, would you?
Remember that the reflection that is being proposed for C++ is static (compile-time) reflection, not the "dynamic" (runtime) reflection seen in some other languages.
Needing to do specific checks for a class type when using a class is often the sign of a badly designed class structure.
I can't really disagree with this, but, I will say that having things know what they are via an explicit field you throw into them (enum, usually) is often very handy. Maybe its admitting your design isnt perfect to inject such a thing -- its a back door of sorts, really-- but it would certainly solve the OP's ask (if thing.type == e_person cout thing.name). Ive used this a bit when the target was a union, instead of OOP, where it makes more sense.
>Needing to do specific checks for a class type when using a class is often the sign of a badly designed class structure.
Specific checks (at compile-time) for the properties of a type is often required in well designed generic code.
That is the raison d'ĂȘtre for the existence of <type_traits> and standard traits helper types ( std::allocator_traits<>, std::iterator_traits<> etc. ).
And for the interest in adding static reflection facilities to the language.