Reputation: 3458
I have two classes A
and B
which derive from the same base class Base
.
I am defining in main a vector Base *
and I use it for storing elements both of A
and B
.
Using a reinterpret_cast I am able to call methods of their real class.
Is this code safe? Is there a better/standard way of doing that?
The two classes in the real code share most of the methods from the base class but the A
possesses some methods not shared with Base
or B
and the same for B
, so virtual is not an option.
#include <iostream>
#include <vector>
class Base {
};
class A : public Base {
public:
void print_from_A() {
std::cout << "hello from A\n";
}
};
class B : public Base {
public:
int number;
void read_from_B() {
std::cin >> number;
}
};
int main(int argc, char * argv[]) {
std::vector<Base*> v;
v.push_back(new A());
v.push_back(new B());
(reinterpret_cast<A *>(v[0]))->print_from_A();
(reinterpret_cast<B *>(v[1]))->read_from_B();
for(auto && e: v) {
delete e;
}
return 0;
}
EDIT:
It seems that using reinterpret_cast
is undefined behaviour: Casting to one class and calling function from sibling class?
It also seems that the correct way is using a static_cast
: Can I get polymorphic behavior without using virtual functions?
Is this the answer?
Upvotes: 1
Views: 124
Reputation: 206747
Is there a better/standard way of doing that?
It is better to use a virtual
member function.
If you are not able to use a virtual
member function, perform a dynamic_cast
, check the status of the cast, and call the member function only if the cast succeeds.
Please note that the base class needs to have a virtual
member function for dynamic_cast
to work. In such cases, it is is recommended to make at least the destructor a virtual
member function.
Here's an updated version of your program using virtual
member functions:
#include <iostream>
#include <vector>
class Base {
public:
virtual ~Base() {}
virtual void print() const = 0;
virtual void read() = 0;
};
class A : public Base {
public:
virtual void print() const {
std::cout << "hello from A\n";
}
virtual void read()
{
// Nothing to do.
}
};
class B : public Base {
public:
int number;
virtual void print() const {
std::cout << "hello from B, " << number << "\n";
}
virtual void read() {
std::cin >> number;
}
};
int main(int argc, char * argv[]) {
std::vector<Base*> v;
v.push_back(new A());
v.push_back(new B());
v[0]->read();
v[0]->print();
v[1]->read();
v[1]->print();
for(auto && e: v) {
delete e;
}
return 0;
}
Upvotes: 1