我有一个头文件(例如the_foo.h),它定义/声明了以下类:

// \file the_foo.h

class FooBase
{
    virtual size_t bar_size() = 0;
};

template<class Bar>
class Foo : public FooBase
{
    size_t  bar_size()  { return sizeof(Bar); }
};

class TheBar;       // TheBar forward declaration

class TheFoo : public Foo<TheBar>
{
};


使用MS vc14(Visual Studio 2015)进行编译时,我注意到以下行为:


任何包含the_foo.h并定义TheBar的cpp文件,例如:

#include "the_foo.h"class TheBar {}; // TheBar definition

将编译就好了。然而,
任何包含the_foo.h并且未定义TheBar的cpp文件,例如:

#include "the_foo.h"

无法编译,并显示错误:the_foo.h(11): error C2027: use of undefined type 'TheBar'

上面编译的cpp文件仅包含一行:包含标题,没有更多代码。
删除虚拟成员函数声明virtual size_t bar_size() = 0;确实可以修复该错误。
感谢Sam Varshavchik的回答,此代码可以使用gcc 5.3.1很好地进行编译,因此,此问题显然是特定于编译器的。


我的问题是:


当仅向前声明TheBar时,为什么在情况(2)中编译失败?
有没有办法使案例(2)在vc14下成功编译,即没有明确定义TheBar,我需要在某些cpp文件中保持哪个类不透明?


PS:我编辑了该问题的代码示例,以弄清是什么真正导致了问题中所述的问题。原始代码示例(在Sam Varshavchik的答案中引用)可能确实误导了问题的实际原因,因此导致了问题范围之外的答案和注释。

最佳答案

您的测试用例编译时不会出现gcc 5.3.1的问题:

$ cat t.C
class FooBase
{
public:
    FooBase()          {}
    virtual ~FooBase() {}
};

template<class Bar>
class Foo : public FooBase
{
public:
    Foo()   { sizeof(Bar); bar = new Bar; }
    ~Foo()  { sizeof(Bar); delete bar; }
    Bar*    bar;
};

class TheBar;

class TheFoo : public Foo<TheBar>
{
public:
    TheFoo();
    ~TheFoo();
};
[mrsam@octopus tmp]$ g++ -c -o t.o t.C
[mrsam@octopus tmp]$


答案似乎是“您使用的旧的C ++编译器无法正确编译”。

10-06 03:32