【问题标题】:Why does this compile if the class is incomplete type?如果类是不完整的类型,为什么会编译?
【发布时间】:2020-10-06 14:56:47
【问题描述】:

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

}

即使在我粘贴到 Memory.h 之后 Foo 还没有完全定义,这也编译得很好。我对为什么会编译感到困惑。编译器粘贴到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

【问题讨论】:

  • #include 是一个简单的复制粘贴,但是 tempate 实例化并不是那么简单的机制。不需要将生成的代码实际放在任何地方,编译器知道它应该做什么就足够了。
  • Memory::newAlloc&lt;Foo&gt;main 中实例化,其中Foo 的定义已完成。
  • 你可以用模板做一些weird and wonderful things
  • 你在问著名的“两阶段查找”。

标签: c++ incomplete-type template-instantiation


【解决方案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 作为模板参数。

【讨论】:

    【解决方案2】:

    即使在我粘贴到 Memory.h 之后 Foo 还没有完全定义,这也能正常编译

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

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

    Foo 的定义已经存在,所以编译正常。


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

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

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

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

    【讨论】:

      猜你喜欢
      • 2018-06-04
      • 1970-01-01
      • 2019-07-16
      • 2012-04-23
      • 2015-02-11
      • 2017-07-03
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多