C++中何时会出现不完整类型错误?

21

有人可以告诉我什么时候C++编译器会抛出“不完整类型错误”吗?

注意:我故意让这个问题留下了一些空间,以便我自己调试代码。


可能带有cv限定符的类型如果没有定义或为void,则是不完整的类型。对象不应被定义为不完整类型。并且,这不是一个好的问题格式。 - Passer By
请参考以下示例:https://dev59.com/SWw15IYBdhLWcg3w3vle - Abdulkadir Dalga
@PasserBy 我找到了一个人回答了我的问题并帮助我找出错误。他比你更有帮助。尽管如此,还是谢谢你。 - Nickal
当我调试用clang++编译的代码时,我复制了一份并切换到g++。 - douyu
4个回答

34

通常这种情况发生在编译器看到一个类型的前向声明但没有看到完整定义时,该类型正在某处被使用。例如:

class A;

class B { A a; };
第二行会导致编译器错误,并且根据编译器的不同,可能会报告不完整的类型(其他编译器会给出不同的错误,但含义相同)。 然而,当您只使用指向这种前向声明的指针时,不会出现任何抱怨,因为类的指针大小始终是已知的。就像这样:
class A;
class B {
   A *a;
   std::shared_ptr<A> aPtr;
};
如果你在使用一个具体的应用程序或库时出现了这个错误,请问可能有什么问题:通常情况下,这种情况发生在包含前向声明的头文件没有找到完整定义的情况下。解决方案非常明显:还要包括可以访问完整类型的头文件。有时,您可能只是没有使用正确的命名空间或者使用了错误的命名空间,需要进行更正。

实际上,在我的情况下,它来自于一个PCL库头文件<window.h>。由于它是一个库文件,因此文件本身不应该有任何错误。应该还有其他东西导致了这个错误。 - Nickal
当头文件被包含在项目中但库未链接时,会发生这种情况吗? - Nickal
不,编译和链接是两个不同的步骤。首先编译器必须创建目标代码(因此需要知道所有使用的类型),然后链接器将它们全部链接到最终的二进制文件中。 - Mike Lischke
谢谢。编辑非常有用。我在包含头文件之前包含了包含完整定义的文件。这样就可以了。 - Nickal
当一个类定义有一个成员其类型为自身时(例如,包含左/右Node指针的二叉树Node类),这也会出现。问题:类指针的大小如何总是已知?它是否具有固定大小(在32位机器上为32位,在64位机器上为64位)? - MTV
它是固定大小的,还是根据架构而定的。但请提出跟进问题,作为自己在SO上的问题。 - Mike Lischke

3
当我们尝试使用一个类/对象或其方法,而它们还没有被定义时,就会出现这种情况。例如:
class A;
class B {
    class A obj;
}

或者

class A;
class B {
    class A *obj;
    B() {   
           obj->some_method();
        }

为了解决这个问题,需要先定义A或者完全声明它(最好在头文件中进行),然后再定义两个类的所有方法(最好在另一个文件中进行)。
class A {
    //definition
}
class B {
class A obj;
}

2

当你在默认析构函数的类中使用前向声明与std::unique_ptr(例如,实现PIMPL惯用语)时,也会出现这种情况。

这个问题在这里得到了很好的解释:Forward declaration with unique_ptr?


1
在我的情况下,这是由于对模板的知识不足。我在模板定义和与该模板相关联的函数之间声明了一个类。
template<typename T>
class
{
  foo a;
  foo b;
};
function(T a,int b)
{

 . . . . .

}

这会带来一些问题,因为模板定义与类相关联,在这种情况下,函数的参数列表中出现错误,提示T未定义,并且不允许使用不完整的类型。如果您需要将模板用于多个实体,则必须在这些实体的定义之前重复使用此语句:

template<typename T>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接