小编典典

我什么时候可以使用前向声明?

all

我正在寻找何时允许在另一个类的头文件中对一个类进行前向声明的定义:

我是否可以为基类、作为成员的类、通过引用传递给成员函数的类等执行此操作?


阅读 104

收藏
2022-03-04

共1个答案

小编典典

把自己放在编译器的位置上:当你前向声明一个类型时,编译器只知道这个类型存在;它对其大小、成员或方法一无所知。这就是为什么它被称为 不完整类型
。因此,您不能使用该类型来声明成员或基类,因为编译器需要知道该类型的布局。

假设以下前向声明。

class X;

这是您可以做和不能做的事情。

你可以用不完整的类型做什么:

  • 将成员声明为指向不完整类型的指针或引用:

    class Foo {
    X *p;
    X &r;
    

    };

  • 声明 接受/返回不完整类型的函数或方法:

    void f1(X);
    

    X f2();

  • 定义 接受/返回指向不完整类型的指针/引用的函数或方法(但不使用其成员):

    void f3(X*, X&) {}
    

    X& f4() {}
    X* f5() {}

你不能用不完整的类型做什么:

  • 将其用作基类

    class Foo : X {} // compiler error!
    
  • 用它来声明一个成员:

    class Foo {
    X m; // compiler error!
    

    };

  • 使用该类型定义 函数或方法

    void f1(X x) {} // compiler error!
    

    X f2() {} // compiler error!

  • 使用其方法或字段,实际上试图取消引用类型不完整的变量

    class Foo {
    X *m;            
    void method()            
    {
        m->someMethod();      // compiler error!
        int i = m->someField; // compiler error!
    }
    

    };


对于模板,没有绝对的规则:是否可以使用不完整的类型作为模板参数,取决于模板中使用该类型的方式。

例如,std::vector<T>要求其参数是完整类型,boost::container::vector<T>而不需要。有时,仅当您使用某些成员函数时才需要完整类型;例如,情况就是这样。std::unique_ptr<T>

一个文档齐全的模板应该在其文档中指出其参数的所有要求,包括它们是否需要是完整的类型。

2022-03-04