dimanche 2 octobre 2016

Cannot convert NULL to a pointer-to-object type

I've not been able to find an explanation of the following on Google so far, and it's confusing me a little.

I have a Scene which stores hierarchies of SceneObjects. The Scene acts as a templated SceneObject factory, so that bookkeeping can be done when a SceneObject subclass instance is created or deleted. Both of these classes are in a dynamically linked module of their own and are within a module namespace (not sure whether this matters).

The (simplified) SceneObject class looks like this:

// SceneObject is a base class, but is not pure.
class SceneObject
{
    // The parent Scene needs to be able to access protected functions.
    friend class Scene;

protected:
    // This is protected to enforce the factory design pattern.
    // We don't want SceneObjects created without being tied to a Scene.
    SceneObject(Scene* parentScene, SceneObject* parentObject);

public:
    ...
};

And the (simplified) Scene class looks like this:

class Scene
{
public:

    // General bookkeeping - a fully constructed subclass is required
    // here as the subclass constructor sets certain member variables.
    void processSceneObjectCreated(SceneObject* object);

    // This function means we can do:
    //   SceneObjectSub* obj = scene.createSceneObject<SceneObjectSub>(...)
    // and pass whatever parameters are required for that particular
    // subclass' constructor, while ensuring the Scene can keep a record
    // of the created object.
    //
    // We can't call processSceneObjectCreated() in the SceneObject base
    // class' constructor, as the required subclass constructor will not
    // have been run yet.
    template<typename T, typename... Args>
    T* createSceneObject(Args... args)
    {
        T* obj = new T(this, std::move(args)...);
        processSceneObjectCreated(obj);
        return obj;
    }

    ...
};

As a test, I compiled the following code to create a new SceneObject:

ModuleNS::Scene scene;
ModuleNS::SceneObject* sceneObject =
    scene.createSceneObject<ModuleNS::SceneObject>(NULL);

However, the MSVC compiler gave me the following error:

Cannot convert argument 2 from 'int' to 'ModuleNS::SceneObject*'

This confused me, as I thought NULL (ie. 0) could always be converted to a pointer type. If instead I use static_cast<ModuleNS::SceneObject*>(NULL), or nullptr (which I'd like to use, but for the sake of consistency with old code I've been using NULL instead), the compile error goes away.

What specifically causes NULL to stop being castable to a pointer?

Aucun commentaire:

Enregistrer un commentaire