Pergunta

I came across an instance the other day where I had a function taking a pointer to a base type which I then needed to up-cast to a derived type to access some additional functionality. However, dynamic_cast failed, which was odd because my type definitely inherited the base type.

To get to the bottom of what was going on, I created the following test program, which I think replicates what I was seeing:

void cast(TestClass *baseType)
{
    if (dynamic_cast<Derived *>(baseType))
        TRACE("cast was sucessful");
    else
        TRACE("cast failed");
}

int main(int argc, char *argv[])
{
    Derived *test1 = new Derived();
    TestClass *test2 = new TestClass();
    TestClass test3;

    test1->identify(); // prints: this is a Derived class
    test2->identify(); // prints: this is a TestClass

    cast(test1); // succesful
    cast(test2); // fail - expected

    // reassign test2 to test1
    test2 = test1;
    test2->identify(); // prints: this is a Derived class

    cast(test2); // succesful

    // the interesting part, the test3 object (created on stack), does not cast
    // despite that it would seem possible from the cast method.
    test3 = *test1;
    test3.identify(); // prints: this is a TestClass
    cast(&test3); // fails?

    return a.exec();
}

Which is interesting, because if you were presented with only the method I called cast(), you would expect it to be possible to cast the object passed in. I've demonstrated that this isn't the case; it depends on how the object is originally created. What is confusing, is why it is possible to cast an object which has been reassigned by reference but not by value. Furthermore, would using static_cast work, as long as we guarantee the types are compatible?

Foi útil?

Solução

test3 is of type TestClass (which I assume is the parent of Derived), so the dynamic cast fails.

Even though you assign *test1 to it, the assignment only copies the TestClass part (aka slicing). When you assign a pointer to a pointer, no slicing occurs.

You can think of derived objects as having a part of their base:

*test1:
|--------------|
|TestClass part|
|--------------|
|Derived part  |
|--------------|

test3:
|--------------|
|TestClass part|
|--------------|

When you assign a pointer (test2=test1), the object itself does not change, you are just looking at it via a different glass (through a pointer to TestClass), thus casting works.

When you assign an object itself (test3=*test1), the destination (test3) has room only for a TestClass object, so the copy takes away the extra Derived part.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top