Search code examples
c++dynamic-cast

Exception thrown when trying to access a protected variable from a child class after a dynamic casting


I am trying to learn about dynamic casting in C++.

So I have developed 2 classes to test some things related to dynamic casting:

class Entity {
protected:
    int x = 10;
public:
    virtual void f1() { cout << "f1 from Entity class" << endl; }
};

class Player : public Entity {
public:
    void f1() { cout << "f1 from Player class" << endl; }
    int f2() { return x; }
    void f3() { cout << "f3 from Player class" << endl; }
};

The method f2() returns x that is defined in the Parent Class Entity.

And here is the main:

int main() {
    Entity* e = new Entity;

    Player* p = dynamic_cast<Player*>(e);
    cout << p->f2() << endl;

    
    //the program prints : "p is not null"
    if(p == nullptr)
        cout << "p is null";
    else
        cout << "p is not null";

    return 0;
}

An exception is thrown when calling p->f2(), specifically on line return x; and it says:

Exception thrown: read access violation. this was nullptr.

The strange thing here is that x is a protected variable, so it must exist at Entity and Player objects, but after the dynamic casting from Entity to Player, the new object can not access it.

So what is the exception reason?

Note: When doing static casting instead of dynamic, p->f2() gives 10 normally


Solution

  • dynamic_cast will never lie. It checks the runtime type of the object to see if it matches the T gi8ven in the dynamic_cast<T>. You created an instance of the Entity base class. The runtime type of this object is Entity because that's what you created.

    dynamic_cast knows the runtime type of the object, so it knows dynamic_cast<Player*> cannot work since the object isn't a Player object. Therefore, it returns nullptr.

    static_cast doesn't know if the object is a Player or not; it assumes that it is and returns a pointer to that object if it is there. But since it's not there, any attempt to use the result of the static_cast yields undefined behavior.

    Which just so happens to do what you want, but there's no guarantee of that.