【发布时间】:2016-08-02 23:00:18
【问题描述】:
我有一个头文件(比如 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 和 DOES NOT DEFINE
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 编译得很好,所以这个问题显然是特定于编译器的。
我的问题是:
- 为什么在情况 (2) 中编译失败,当
TheBar仅前向声明时? - 有什么方法可以让案例(2)在 vc14 下编译成功,即没有明确定义
TheBar,我需要在某些 cpp 文件中保持哪个类不透明?
PS:我编辑了这个问题的代码示例,以明确导致问题中描述的问题的真正原因。原始代码示例(在 Sam Varshavchik 的回答中引用)可能确实误导了问题的实际原因,因此导致答案和 cmets 超出了问题范围。
【问题讨论】:
-
您在这里尝试做的是创建和删除前向声明的类。编译器不知道构造函数或析构函数。所以它不应该工作。如果您需要隐藏声明,请考虑更好的对象管理系统。
-
@teivaz:据我了解 C++,我不尝试在我的示例中创建任何内容:我只包含 the_foo.h 头文件并且不实例化任何内容;如果我确实在没有定义 TheBar 的情况下实例化了 TheFoo,编译器将在 Foo() 构造函数处失败。在我的示例中,编译器在 TheFoo 析构函数中失败,而不是在构造函数中。
-
@SharpDressedMan,这里的编译器尝试生成具有所有功能的类。根据 RAII 的析构函数将调用未为前向声明的类定义的析构函数。
-
顺便说一句,以下代码在离开范围后会崩溃:
TheFoo f1, f2; f1 = f2;。您需要定义正确的复制构造函数或禁止它。
标签: c++ templates visual-c++ abstract-class forward-declaration