views:

105

answers:

1

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.

+1  A: 

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.)

sth