什么情况下使用前置声明?

什么情况下使用前置声明?

我们这个时候可以先站在编译器的角度来思考这个问题:当你前置声明一个类型时,编译器就会知道这个类型的存在,但没法知道它的布局、大小、成员…所以我们也把前置声明的类型叫做不完全类型(incomplete type)。

假如你有下面的前置声明,

class X;

那么你可以做的如下

  1. 定义一个指针或引用

    class Foo {    X *p;    X &r;};
    
  2. 函数参数或返回值,但没法使用它们的成员变量或函数

    void f1(X);X    f2();void f3(X*, X&)X&   f4()X*   f5()
    

你不能做的如下

  1. 用作基类

    class Foo : X {} // compiler error!
    
  2. 定义变量

    class Foo {    X m; // compiler error!};void f1(X x) {} // compiler error!X    f2()    {} // compiler error,注意这里有个 {},和上面的是不同的
    
  3. 无法访问成员变量和成员函数

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

那么模板如何前置声明呢?例如以下的类模板,

template<typename Type, typename IDType=typename Type::IDType>class Mappings{public:    ...    Type valueFor(const IDType& id) { // return value }    ...};

前置声明就是,

template<typename Type, typename IDType=typename Type::IDType> // 注意它的默认参数class Mappings;

C++ 标准容器,例如 std::vector std::list 的前置声明需要加上它的命名空间,例如,

namespace std {  template<class T, class Allocator = std::allocator<T>>  class list;}

猜你喜欢

转载自blog.csdn.net/xu_fu_yong/article/details/124040391