0

在 Memory.h 我有:

#pragma once

class Memory
{public:
    template <typename T, typename ... TArgs>
    static T* newAlloc(TArgs ... args)
    {
        return new T(args ...);
    }
};

在 main.cpp 我有:

#include "Memory.h" // The template class is defined here

class Foo
{public:
    Foo(int a, const char* c) {}
};

int main()
{
    Memory::newAlloc<Foo>(7, "str");

}

即使 Foo 直到我粘贴到 Memory.h 之后才完全定义,这编译得很好。我对为什么会编译感到困惑。编译器粘贴到 Memory.h 后的等效代码在 main.cpp 中是不是这样:

class Memory
{
public:
    static Foo* newAlloc(int a, const char* c)
    {
        return new Foo(a, c);
    }
};

class Foo
{public:
    Foo(int a, const char* c) {}
};

int main()
{
      Memory::newAlloc(7, "str");
}

???因为这不能编译,所以我收到错误:

'newAlloc' 标识符未找到 'newAlloc' 不是内存的成员

基本上它想要 Foo 的完整定义。如果我将 Foo 类定义放在 Memory 之上,那么它编译得很好。因此,鉴于我的第二个版本相当于模板实例化后的代码(是吗?)那么为什么第一个版本可以编译,而第二个版本不能?

我在 Visual Studio 2019 16.4.5

4

2 回答 2

1

编译器粘贴到 Memory.h 后的等效代码在 main.cpp 中是不是这样:

不,这不是真的。这将是等效的:

class Memory
{public:
    template <typename T, typename ... TArgs>
    static T* newAlloc(TArgs ... args)
    {
        return new T(args ...);
    }
};


class Foo
{public:
    Foo(int a, const char* c) {}
};

int main()
{
    Memory::newAlloc<Foo>(7, "str");

}

你会发现这可以编译。

为什么第一个版本编译

它之所以有效,Foo是因为在模板实例化之前定义Foo为模板参数。

于 2020-10-06T15:02:45.660 回答
1

即使 Foo 直到我粘贴到 Memory.h 之后才完全定义,这编译得很好

是的,因为此时Memory::newAlloc已在此处实例化:

Memory::newAlloc(7, "str");

的定义Foo已经存在,所以编译得很好。


编译器粘贴到 Memory.h 后的等效代码在 main.cpp 中是不是这样:

不,在这种情况下,在这一行:

static Foo* newAlloc(int a, const char* c)

由于Foo尚未定义,代码将无法编译。

于 2020-10-06T15:03:19.370 回答