【问题标题】:Forward declaration of a class in a namespace命名空间中类的前向声明
【发布时间】:2012-12-27 02:09:00
【问题描述】:

如何在命名空间中转发声明一个类。例如下面是一个库的头文件,用户不需要知道私有 myPtr 所以在包含下面的头文件时不需要包含 boost 头文件。那么如何转发声明 boost::shared_ptr 以启用用户代码编译?

MyClass.h

class MyClass
{

private:

  boost::shared_ptr<Mytype> myPtr;

}

【问题讨论】:

  • @JaredC 如果他提供了预编译库,则不会。
  • @korhan 我不确定我是否完全理解您的问题,但听起来可能与我最近提出的问题相似 - 看看这里的答案,看看是否有帮助:@987654321 @
  • 你试图让这个小宝石的消费者不必包含 boost 标头来获得你希望他们一开始不知道的东西的定义;总结一下吗?
  • @Jon thx 用于重播,我刚刚检查过,但我的问题是在消费者不知道的命名空间中前向声明一个类(或者我不需要知道 aobut。)跨度>
  • @WhozCraig 是的,这就是我想要做的。顺便说一句,我的库是一个静态库,如果它改变了任何东西

标签: c++ namespaces


【解决方案1】:

TL;DR 此处需要包含&lt;boost/shared_ptr.hpp&gt;。没有(智能)方式解决它。 MyType 本身可以前向声明。

当然,您可以在标题顶部写上#include &lt;boost/shared_ptr.hpp&gt;,这样您的用户就不必自己动手了。提供 autonomous 标头(即可以首先包含而不会出错的标头)实际上是一种很好的做法。


前向编译的规则稍微复杂一些。理解它们的原因比尝试记住所有案例更容易。

有两个因素:

  • 语义
  • 内存属性(大小和对齐方式)

语义:为了访问对象的方法、属性或基类,您需要了解它们。当然,看起来很明显,除了构造函数、赋值运算符和析构函数,即使是自动生成的,也是方法。很容易忘记它们。

内存属性:与大多数语言不同,C++ 试图尽可能高效,这意味着它将为对象分配内存就在那儿,而不是在某处分配它并且只在使用点使用指针,除非您当然指示它这样做(通过使用 pointerreference)。为了知道分配多少,编译器需要查看对象的guts,即引擎盖下的内容。这意味着即使无法访问确切的详细信息(private/protected 的东西),它们也需要可见,以便可以看到需要在 8 字节边界上对齐的 24 个字节(与 shared_ptr 无关方式)。

在标准中,我们说对象的定义对于这两种需求(方法和内存布局)中的任何一种都是必需的。如果需要定义,那么它必须是显而易见的。


好的,既然我们知道了原因,我们就可以检查各种事情了。在以下情况下是否需要定义:

  • 使用对象作为sizeofalignof 的参数? (显然,需要内存属性)
  • 使用对象作为属性? (需要内存属性)
  • 使用对象作为静态属性? (1)
  • 使用对象的指针或引用作为属性? (2)
  • 在函数声明中使用对象作为参数? (3)
  • 在函数声明中使用对象作为返回类型? (3)
  • 传递指向对象的指针或引用? (4)
  • 转换为基类? (基类存在和可访问性的语义检查)
  • 转换成另一种类型? 取决于 (5)

(1) 声明不需要任何东西,但是静态属性的定义需要对象的定义。

(2) 指针是 32 位或 64 位大(取决于您如何编译,...),与对象无关。引用具有实现定义的表示。

(3) 即使按值取/返回!函数定义(如果在其中使用)或函数调用站点可能需要它。

(4) 当然,如果您尝试使用它(p-&gt;foo()p.foo()),那就另当别论了。

(5) 如果需要使用对象的转换操作符,那么显然是必须的;否则,如果您使用其他类型的构造函数,则适用与函数相同的规则(但需要其他类型定义)。

我希望现在情况更清楚了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2015-05-10
    • 1970-01-01
    • 2011-09-20
    相关资源
    最近更新 更多