Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

By accident I found that with a polymorphic type using dynamic_cast back to the

ID: 658528 • Letter: B

Question

By accident I found that with a polymorphic type using dynamic_cast back to the derived class will throw a 'bad cast' error if the pointer is no longer valid. Is this undefined behavior or could this be a way to check for valid pointers without using smart pointers?

I'm not really against using smart pointers as they serve a real need, but I dislike the syntax. I don't have anything against templated types but I find smart pointers to bloat the code and I'm not a fan of macro's to try and avoid that bloat. I wish C++ included something in the language syntax itself vs using the template feature but with this question I'm more concerned about what is happening below and if this is a valid and defined way to checking for valid pointers as this gives an exception every time from my tests.

#include <string>
#include <map>


using namespace std;

class Base
{
public:
    virtual ~Base(){}
};

class Derived : public Base
{
public:
    virtual ~Derived(){}
};

class Storage
{
private:
    map<string, Base*> storage;
public:
    void AddItem(string name, Base* base)
    {
        if (storage.find(name) == storage.end())
        {
            storage[name] = base;
        }
    }

    template <class T>
    T& FindItem(string name)
    {
        if (storage.find(name) != storage.end())
        {
            Base* item = storage[name];

            return dynamic_cast<T&>(*item);
        }

        throw;
    }
};

int main()
{
    Storage store;

    // force 'd' to go out of scope for our test
    {
        Derived d;

        store.AddItem("test", &d);
    }

    // this will throw a bad cast exception
    Derived& test = store.FindItem<Derived>("test");


    return 0;
}

Explanation / Answer

dynamic-cast needs to deference the pointer to find the proper offset it should be at, dereferencing an invalid pointer is undefined behavior,

one thing you might see:

class Derived2 : public Base
{
public:
virtual ~Derived2(){}
};

int main()
{
Storage store;

{
Derived d;

store.AddItem("test", &d);
}

{
Derived2 d2;

Derived2& test = store.FindItem<Derived2>("test");//might not throw an exception
//test might refer to d2
}


return 0;
}
Messing about with a void* buffer and placement new and destroy will let me insert anything in there.

Just go with smart pointers and learn to appreciate them for the blessing that they are.