C++ 无法将NULL转换为指向对象类型的指针

C++ 无法将NULL转换为指向对象类型的指针,c++,c++11,pointers,C++,C++11,Pointers,到目前为止,我还无法在谷歌上找到以下内容的解释,这让我有点困惑 我有一个场景,它存储场景对象的层次结构。场景充当模板化的场景对象工厂,以便在创建或删除场景对象子类实例时可以进行簿记。这两个类都位于自己的动态链接模块中,并且位于模块名称空间中(不确定这是否重要) (简化的)SceneObject类如下所示: // SceneObject is a base class, but is not pure. class SceneObject { // The parent Scene nee

到目前为止,我还无法在谷歌上找到以下内容的解释,这让我有点困惑

我有一个
场景
,它存储
场景对象的层次结构
场景
充当模板化的
场景对象
工厂,以便在创建或删除
场景对象
子类实例时可以进行簿记。这两个类都位于自己的动态链接模块中,并且位于模块名称空间中(不确定这是否重要)

(简化的)
SceneObject
类如下所示:

// 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:
    ...
};
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;
    }

    ...
};
(简化的)
场景
类如下所示:

// 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:
    ...
};
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;
    }

    ...
};
但是,MSVC编译器给了我以下错误:

无法将参数2从“int”转换为“ModuleNS::SceneObject*”

这让我很困惑,因为我认为
NULL
(即0)总是可以转换为指针类型。如果我改为使用
static_cast(NULL)
,或
nullptr
(我很想使用它,但为了与我一直使用的
NULL
旧代码保持一致),编译错误就会消失


是什么具体导致NULL不再可强制转换为指针?

用C++的
nullptr
替换
NULL


NULL扩展为的0值在通过
std::move
清洗时会“在翻译中丢失”,错误的性质与以下示例中的错误相同

template <typename T> void foo(T t) {
    void *p = t; // ERROR here
}

int main() {
    foo(NULL);
}
模板无效foo(T){
void*p=t;//此处有错误
}
int main(){
foo(空);
}
在C++中,只有文字>代码> 0代码>代码可以转换为指针类型,以生成空指针值。code>NULL扩展为文本零,这就是为什么可以使用它直接初始化/分配/比较指针。“直接”是这里的关键词

但是,一旦通过函数参数输入它,它就不再是文本
0
,也不能再充当空指针常量

在上面的例子中,
T
被推断为某种整数类型。函数中的
t
只是一个[run-time]整数,正好有值
0
。并且不允许使用任意整数初始化指针


注意,在现代C++ >代码> NUL>代码>中,实际上可以定义为代码> NulLPTR < /C>,这将使上述代码编译。但对于

NULL
(作为整数
0
)的“传统”定义,它不会这样做。

指针可以是64位。整数可以是32位?检查这里:我在64位系统上,所以这可能确实适用。我以前从未在项目中的任何其他代码中遇到过这个问题,所以我很好奇这段代码到底是什么导致了这个错误。你能不能再扩展一下“翻译中丢失”的意思?那么
std::move
就是罪魁祸首?我不知道它会有那样的效果,但我想这是有道理的。我可能会回去重新编写代码,以一致地使用
nullptr
。在这种情况下,可能值得付出努力。
std::move
与此无关。该错误是由以下事实引起的:
NULL
作为空指针常量的资格在通过函数参数列表后无法继续存在。我假设
NULL
0
的类型由模板系统推断为整数参数。将其类型设置为整数后,模板将生成一个
int
参数。我想这就是它在翻译中丢失的地方。
std::move
可能会导致这样的错误,因为它也是一个模板函数,所以
std::move(NULL)
将返回一个
int
而不是
nullptr\t
。但是在代码示例中,即使删除了
std::move
,您仍然会遇到AnT解释的问题。