Reputation: 57678
The dynamic_cast
operator is returning zero (0) when I apply to a pointer that points to an instance of a multiply inherited object. I don't understand why.
The hierarchy:
class Field_Interface
{
public:
virtual const std::string get_field_name(void) const = 0; // Just to make the class abstract.
};
class Record_ID_Interface
{
public:
virtual bool has_valid_id(void) const = 0;
};
class Record_ID_As_Field
: public Field_Interface,
public Record_ID_Interface
{
// This class behaves as a Field and a Record_ID.
// ...
}
// A demonstration function
void Print_Field_Name(const Field_Interface * p_field)
{
if (p_field)
{
cout << p_field->get_field_name() << endl;
}
return;
}
// A main function for demonstration
int main(void)
{
Record_ID_As_Field * p_record_id = 0;
p_record_id = new Record_ID_As_Field;
if (p_record_id)
{
// (1) This is the trouble line
Print_Field_Name(dynamic_cast<Field_Interface *>(p_record_id));
}
return 0;
}
I want to have the Record_ID_As_Field
to be treated as a Field_Interface
, but also fit in where Record_ID_Interface
are required.
Why is dynamic_cast
in (1) above returning 0, and how do I resolve this?
I am using Visual Studion 2008 on Windows XP.
Note: For simplicity, I am using fundamental pointers in this example. Actual code uses boost::shared_ptr
.
Upvotes: 1
Views: 2482
Reputation: 229563
Note: For simplicity, I am using fundamental pointers in this example. Actual code uses
boost::shared_ptr
.
And that's your problem right there: You cannot dynamic_cast
a shared_ptr<A>
to a shared_ptr<B>
since those two types are not actually related to each other, even if A
and B
are.
Luckily in the specific case in your question the dynamic_cast
shouldn't be necessary, since Record_ID_As_Field*
should be implicitly convertible to a Field_Interface*
(since the one is derived from the other). shared_ptr
implements conversion operators that lift these implicit conversions to the respective shared_ptr
objects, so shared_ptr<Record_ID_As_Field>
should be implicitly convertible to shared_ptr<Field_Interface>
.
If you leave out the dynamic_cast
, it should work.
If you'd actually need to do a dynamic cast, you could use a special constructor provided by shared_ptr
:
shared_ptr<Record_ID_As_Field> raf;
shared_ptr<Field_Interface> fi(raf, dynamic_cast<FieldInterface*>(raf.get());
(I'm not sure what would happen there if the dynamic_cast
fails, so you should investigate what's the best way to handle that situation.)
Upvotes: 2