我有一个头文件(例如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 ++编译器无法正确编译”。