在从抽象类继承的模板类中正确使用未定义的类型
Proper use of undefined type in template class inheriting from abstract class
我有一个头文件(比如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)编译时,我注意到以下行为:
任何包含_foo.h并定义
TheBar
的cpp文件,例如:#include "the_foo.h" class TheBar {}; // TheBar definition
会编译得很好。然而,
任何包含_foo.h和的cpp文件都不会定义
TheBar
,例如:#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)中编译失败 - 有没有任何方法可以使case(2)在vc14下成功编译,即没有
TheBar
的明确定义,我需要在一些cpp文件中保持哪个类的不透明性
附言:我编辑了这个问题的代码示例,以明确问题中描述的问题的实际原因。原始代码样本(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++编译器,它没有正确编译这个"。
Foo
类的构造函数和析构函数中构造或删除class TheBar
时,编译器会搜索它的定义。这意味着它需要在这一点上实现,否则它不知道该做什么
如果做以下例子:
第一个标题:
// 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
将解决这个问题。
相关文章:
- 在UE4中使用未定义类型'UTextBlock'
- 删除[]具有不同类型的未定义行为?
- 在硬件SIMD矢量指针和相应类型之间进行"interpret_cast"是一种未定义的行为吗
- 错误:未定义对"静脉类型信息::电池访问"的引用
- 在头文件中使用opencv类型来实现未定义的标识符
- 为什么这种类型的双关语不是未定义的行为?
- 在C++中,转换为simd类型是否有未定义的行为
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 交换未定义数据类型中的字节顺序
- 具有未声明/未定义类型的 typedef 结构
- 对静态常量积分类型的未定义引用
- 为什么 std::memcpy(作为类型双关语的替代方案)不会导致未定义的行为?
- 为什么内置类型的对象上的溢出会导致异常/未定义的行为?
- static_cast实际上不是对象类型的类型是未定义的行为吗?
- 共享库中非模板基的模板子类导致未定义的符号类型信息'class'链接错误
- icu::SimpleDate格式使用未定义类型的编译器错误
- 将不相关类型的对象reinterpret_cast空类是未定义的行为吗?
- 类型特征检查 CRTP 派生,在基类中,问题是未定义的类型
- std::is_arithmetic 为通用 lambda 中的 int 类型返回 false:未定义的行为?
- 使用 char16_t 类型作为 char[] 数组,并通过 reinterpret_cast<> 重新转换它。我的代码是否有未定义的行为?