在test.h
:
#ifndef TEST_H
#define TEST_H
#include <map>
struct Incomplete;
class Test {
std::map<int, Incomplete> member;
public:
Test();
int foo() { return 0; }
};
#endif
在test.cpp
:
#include "test.h"
struct Incomplete {};
Test::Test() {}
在main.cpp
#include "test.h"
int main() {
Test test;
return test.foo();
}
g ++ 4.7在写struct Incomplete
时给出了g++ main.cpp test.h -o main.o
向前声明的错误。
但是,如果我将std::map<int, Incomplete> member
更改为std::map<int, Incomplete*> member
,则main.o
会进行编译。为什么是这样?
答案 0 :(得分:4)
为什么会这样?
因为C ++标准库容器未定义为使用不完整的成员类型。 This is by design 1 - 但它可以说是一个错误(可能会在将来的C ++版本中更改)。 Boost.Containers库修复此问题。
带指针的代码有效,因为指向不完整类型的指针本身就是一个完整的类型。但是,这显然会极大地改变你的类型的语义(特别是,谁管理内存?),并且通常不好用它作为替代。
1 值得指出的是,该文章声称您在技术上无法实施std::map
来处理不完整类型。但是,这种说法是错误的。
答案 1 :(得分:0)
当您转发声明类型时,您基本上声明存在具有该名称的类型,仅此而已。编译器不知道它的大小,成员等。它被称为不完整类型,除了声明指针或引用之外不能用于任何其他内容。这是可能的,因为指针的大小,无论其类型如何,在同一平台上都是相同的。
答案 2 :(得分:0)
前向声明意味着“此类/结构/稍后将在代码中的任何内容”。容器需要知道结构存储记录的大小。在技术方面,您使用的是不完整类型。
由于指针在大多数机器上都是固定大小(x64通常有8个字节的指针),因此在编译时不需要查看结构的完整定义,因为您不需要“计算”多少在地图中为该结构保留的空间:您只需要指针所需的空间。