C++ 如果类是不完整类型,为什么要编译?

C++ 如果类是不完整类型,为什么要编译?,c++,incomplete-type,template-instantiation,C++,Incomplete Type,Template Instantiation,在内存中,我有: #pragma once class Memory {public: template <typename T, typename ... TArgs> static T* newAlloc(TArgs ... args) { return new T(args ...); } }; ???因为这没有编译,所以我得到了错误: 未找到“newAlloc”标识符“newAlloc”不是的成员 记忆 基本上,它需要Foo

在内存中,我有:

#pragma once

class Memory
{public:
    template <typename T, typename ... TArgs>
    static T* newAlloc(TArgs ... args)
    {
        return new T(args ...);
    }
};
???因为这没有编译,所以我得到了错误:

未找到“newAlloc”标识符“newAlloc”不是的成员 记忆

基本上,它需要Foo的完整定义。如果我将Foo类定义放在内存定义之上,那么它就可以很好地编译。既然我的第二个版本相当于模板实例化后的代码(是吗?),那么为什么第一个版本编译而第二个版本不编译呢

我使用的是Visual Studio 2019 16.4.5

编译器粘贴到内存后的等效代码不是吗。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");
}
不,这不是真的。这相当于:

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");

}
类内存
{公众:
模板
静态T*newAlloc(目标…参数)
{
返回新的T(参数…);
}
};
福班
{公众:
Foo(inta,constchar*c){}
};
int main()
{
内存:newAlloc(7,“str”);
}
你会发现它可以编译

为什么第一个版本要编译

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

编译器粘贴到内存后的等效代码不是吗。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");
}
不,这不是真的。这相当于:

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");

}
类内存
{公众:
模板
静态T*newAlloc(目标…参数)
{
返回新的T(参数…);
}
};
福班
{公众:
Foo(inta,constchar*c){}
};
int main()
{
内存:newAlloc(7,“str”);
}
你会发现它可以编译

为什么第一个版本要编译

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

即使在我粘贴到Memory.h之后才完全定义Foo,这也可以很好地编译

是的,因为在这里实例化
Memory::newAlloc
时:

Memory::newAlloc(7, "str");
Foo
的定义已经存在,因此编译起来很好


编译器粘贴到内存后的等效代码不是吗。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");
}
不,在本例中,在这一行:

static Foo* newAlloc(int a, const char* c)
由于尚未定义
Foo
,因此代码将不会编译

即使在我粘贴到Memory.h之后才完全定义Foo,这也可以很好地编译

是的,因为在这里实例化
Memory::newAlloc
时:

Memory::newAlloc(7, "str");
Foo
的定义已经存在,因此编译起来很好


编译器粘贴到内存后的等效代码不是吗。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");
}
不,在本例中,在这一行:

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

由于尚未定义
Foo
,代码将不会编译。

#include
是一个简单的复制粘贴,但tempate实例化并不是那么简单的机制。无需实际将生成的代码放在任何地方,只要编译器知道它应该做什么就足够了。
Memory::newAlloc
main
中实例化,其中
Foo
的定义已完成。您可以使用模板进行一些操作。您正在询问著名的“两阶段查找”.
#include
是一种简单的复制粘贴,但tempate实例化并不是那么简单的机制。无需实际将生成的代码放在任何地方,只要编译器知道它应该做什么就足够了。
Memory::newAlloc
main
中实例化,其中
Foo
的定义已完成。您可以使用模板进行一些操作。您正在询问著名的“两阶段查找”。