我有一个头文件(比如说 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
只是前向声明?TheBar
的明确定义,哪个类需要在某些cpp文件中保持不透明?PS:我编辑了这个问题的代码示例,以便明确究竟是什么原因导致了问题中描述的问题。原始代码示例(在Sam Varshavchik的回答中引用)可能确实误导了问题的实际原因,并因此导致了问题范围之外的答案和评论。
答案 0 :(得分:1)
您的测试用例编译时没有遇到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]$
这里的答案似乎是&#34;你正在使用一个没有正确编译它的旧C ++编译器&#34;。
答案 1 :(得分:0)
当您尝试在class TheBar
类的构造函数和析构函数中构造或删除Foo
时,编译器会搜索该// foobase.h
class FooBase
{
public:
FooBase() {}
virtual ~FooBase() {}
};
template<class Bar>
class Foo : public FooBase
{
public:
Foo() { bar = new Bar; }
~Foo() { delete bar; }
private:
Bar* bar;
};
class TheBar;
class TheFoo : public Foo<TheBar>
{
public:
TheFoo() {};
~TheFoo() {};
};
的定义。这意味着它需要在那时实现,否则它不知道该怎么做。
如果制作以下示例:
第一个标题:
// thebar.h
class TheBar {};
下一个标题
// foo_main.cxx
// #include "thebar.h" // Including this include makes the program run
#include "foobase.h"
int main()
{
TheFoo thefoo;
return 0;
}
以下主要文件:
./foobase.h:14:32: error: allocation of incomplete type 'TheBar'
Foo() { bar = new Bar; }
然后你的编译器会告诉你什么是错的(只显示第一个错误):
thebar.h
包括 ddlRegisters.Click();
SelectElement selector = new SelectElement(ddlRegisters);
selector.SelectByIndex(1);
String regSelect = selector.Options[1].Text.ToString();
Console.WriteLine("The User Selected "+regSelect+".");
将解决问题。