【问题标题】:Forward declaration outside class works, but not when nested类外的前向声明有效,但嵌套时无效
【发布时间】:2018-06-10 19:08:54
【问题描述】:

假设我有两个类 AB 使用 pimpl 成语。 A 提供公共 API,持有指向 B 的指针。在 A 中前向声明 B 时出现编译错误,但在外部声明时却没有。

为什么后者不起作用?在这两种情况下,在调用B 的任何方法之前,我都将b.hpp 包含在a.cpp 中。

类外转发声明A

这个例子运行正常。

文件a.hpp

#ifndef _A_
#define _A_

#include <memory>

class B; // forward declaration, defined in a.cpp
class A {
public:
        A();
        ~A();
        void Hi();
private:
        std::unique_ptr< B > b_;
};

#endif

文件a.cpp

#include "b.hpp"
#include "a.hpp"

A::A() : b_( std::make_unique< B >() ) { }
A::~A() { }

void
A::Hi() {
        this->b_->Hi();
}

文件b.hpp

#ifndef _B_
#define _B_

class B {
public:
        void Hi();
};

#endif

文件b.cpp

#include "b.hpp"

#include <iostream>

void
B::Hi() {
        std::cout << "Hello World!" << std::endl;
}

驱动文件hello.cpp:

#include "a.hpp"

int main() {
        A a;
        a.Hi();
        return 0;
}

编译:g++ hello.cpp a.cpp b.cpp -std=c++14

在类A内转发声明

这里我将B 的前向声明移动到A 中。

文件a.hpp

#ifndef _A_
#define _A_

#include <memory>

class A {
public:
        A();
        ~A();
        void Hi();
private:
        class B; // forward declaration, defined in a.cpp
        std::unique_ptr< B > b_;
};

#endif

我收到以下编译错误:

a.cpp: In member function ‘void A::Hi()’:
a.cpp:9:10: error: invalid use of incomplete type ‘class A::B’
  this->b_->Hi();
          ^
In file included from a.cpp:2:0:
a.hpp:12:8: error: forward declaration of ‘class A::B’
  class B;
        ^
In file included from /usr/include/c++/4.9/memory:81:0,
                 from a.hpp:4,
                 from a.cpp:2:
/usr/include/c++/4.9/bits/unique_ptr.h: In instantiation of ‘typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = A::B; _Args = {}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<A::B>]’:
a.cpp:4:36:   required from here
/usr/include/c++/4.9/bits/unique_ptr.h:765:69: error: invalid use of incomplete type ‘class A::B’
     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
                                                                     ^
In file included from a.cpp:2:0:
a.hpp:12:8: error: forward declaration of ‘class A::B’
  class B;
        ^
In file included from /usr/include/c++/4.9/memory:81:0,
                 from a.hpp:4,
                 from a.cpp:2:
/usr/include/c++/4.9/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = A::B]’:
/usr/include/c++/4.9/bits/unique_ptr.h:236:16:   required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = A::B; _Dp = std::default_delete<A::B>]’
a.cpp:4:36:   required from here
/usr/include/c++/4.9/bits/unique_ptr.h:74:22: error: invalid application of ‘sizeof’ to incomplete type ‘A::B’
  static_assert(sizeof(_Tp)>0,

【问题讨论】:

  • 第二个示例前向声明类A::B,它与类::B 不同且无关。前者被使用但从未定义。后者已定义但从未使用过。另见:nested classes

标签: c++ forward-declaration pimpl-idiom


【解决方案1】:

这是因为您没有声明相同的class BB 在您的第二个示例中被声明为 嵌套类。它的范围为A::(因为它实际上被命名为类A::B)。但随后您尝试将其用作::B(在全局范围内)。

这从错误消息中很明显:

错误:无效使用不完整类型'class A::B'

这行不通。在A 外部前向声明class B 是实现此目的的正确方法。

【讨论】:

  • 谢谢,现在很清楚了。我确实在声明另一个类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 2010-10-31
相关资源
最近更新 更多