【问题标题】:Is it possible to friend a class in an anonymous namespace in C++?是否可以在 C++ 中的匿名命名空间中为类添加好友?
【发布时间】:2023-04-01 14:07:01
【问题描述】:

我正在将代码从 Java 移植到 c++,我想复制一些匿名功能。

在文件 A.h 我有:

class A
{
private:
  int a;

  class AnonClass;
  friend class AnonClass;
};

在文件 A.cpp 我有:

namespace
{
  class AnonClass
  {
  public:
    AnonClass(A* parent)
    {
      parent->a = 0; // This doesn't work, a is not accessible
    }
  }
}

是否可以在 C++ 中为匿名命名空间中的类添加好友?

在 Java 中,您可以声明匿名类,因此它非常相似。它也不会将 AnonClass 暴露给 A.h 的客户

【问题讨论】:

  • 您尝试过这样做吗? (没有“class AnonClass;”行)。 AFAIK,您可以像这样声明它,但是当您使用 AnonClass 时,您必须指定命名空间。是你想要的吗?
  • 坦率地说,我还不能编译,我有大量未修改的函数和类要创建以获得编译的希望。我为此使用 VS2012 错误自动检测。我测试了上面的代码,但它不起作用
  • 如果没有“class AnonClass;”,它也不会编译,因为 AnonClass 未定义
  • 这可能是因为您可能没有前向声明 AnonClass(您必须在使用它之前(在哪里)声明一个类)。您的“class AnonClass”行定义了一个名为 A::AnonClass 的类(A 的内部类),它与另一个不同。您至少需要将“class AnonClass”行放在 A 类定义之上(这不一定能解决您的命名空间问题)。
  • @leewangzhong, 1. 不同类的声明。 2. 你不需要它。

标签: c++ namespaces friend


【解决方案1】:

据我所知,你不能。原因:

  1. “匿名”命名空间只能在您创建它的文件中访问。
  2. 您必须在一个命名空间中定义整个 AnonClass 类及其功能,即在程序中的一个位置。
  3. A 类必须在 AnonClass 构造函数之前定义。
  4. AnonClass 必须至少在 A 类之前声明。

所以你看,你不能在两个部分上破坏 AnonClass 的定义。而且你不能在A类之前和之后都定义它。

唯一的选择 - 将 A 类放入同一个匿名命名空间。此代码有效:

namespace 
{
  class A
  {
   public:
    A():a(0){};
   private:
    int a;

    friend class AnonClass;
  };

  class AnonClass
  {
  public:
    AnonClass(A* parent);
  };

  AnonClass::AnonClass(A* parent)
  {
      parent->a = 0;
  };
}

int main() {
  A a;

  return 0;
}

我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    鲜为人知的替代方法是让 Anon 类成为 A 的成员类。在 A 类中,您只需要一行 class Anon; -- 没有真正的代码,没有朋友声明。请注意,它属于 A 类,几乎与 Java 中一样。在 .cpp 文件中,您写入了有关 Anon 的所有详细信息,但您不是将其放在匿名命名空间中,而是放在A::

      class A::Anon { ..... };
    

    您可以像往常一样拆分 A::Anon 的声明和实现,只需记住始终将 A:: 添加到 Anon。

    类 Anon 是 A 的成员,因此可以访问 A 的所有其他成员。但它对 A 的客户端仍然未知,并且不会弄乱全局命名空间。

    【讨论】:

    • 太棒了,我也不知道这个技巧,非常适合我目前的需求。
    • 我不知道为什么这让我如此惊讶,因为我现在记得它是大多数 pimpl 模式的关键方面 - 但直到现在我才遇到类似的(但完全不是-Java 派生的 ;-) 问题,我必须正确考虑这...和 ​​WOW 的含义。 mind = blown; 我之前使用的是 friend class,但不知何故感觉不对,而这是我想要的更好的表达。
    • 遗憾的是这些仍然有外部链接。希望使用模块可以创建完全内部的类,仅在模块内可见,但仍然能够将它们声明为同一模块中其他类的朋友。
    猜你喜欢
    • 2018-06-24
    • 2019-10-29
    • 1970-01-01
    • 2017-10-25
    • 2020-07-20
    • 2012-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多