【问题标题】:Befriending a class结交班级
【发布时间】:2010-08-25 14:53:42
【问题描述】:

我正在尝试与一个类交朋友,以便它能够访问它的私有构造函数。

在 some_file.h 中

class B;    

namespace some_name {
class A {
  public:
    A() {}
  private:
    A (int x) {}
    friend class ::B;
};
}

在 other_file.h 中

#include "some_file"

namespace {
class B {
  protected:
    A* get_a(int x) { return new A(x); }
};   
}

编译这段代码时,我得到 - 错误:'some_name::A::A(int)' 是私有的。

我现在,它是私人的,这就是我与 B 成为朋友的原因。 我在这里做错了什么? 你不能和你的构造函数交朋友吗? 有命名空间问题吗?

谢谢

【问题讨论】:

  • 要与其他班级交朋友,只需戴上礼帽,带上你练习过的捻转手杖,以及一些带有新鲜皮革气味的漂亮鞋子。 “那个眼睛里闪烁着光芒的男人走了!”人们会发表评论,为新课程打开新机会的大门。

标签: c++ friend


【解决方案1】:

这样做:

namespace {
class B {
  protected:
    A* get_a(int x) { return new A(x) };
}   
}

您没有将 B 放在根(全局)命名空间中,而是放在匿名命名空间中。

所以::B 无法联系到B

如果您希望 B 位于根(全局)命名空间中,请不要用 namespace 将其括起来。这应该可以解决问题。

【讨论】:

  • 好的,但是如果我无法控制 B 的位置并且它必须是匿名命名空间,我怎样才能让它工作?
  • @izex:这个匿名命名空间的作用就是禁止在匿名命名空间之外引用这个类型。除非您将 A 声明移动到同一个匿名命名空间中,否则没有办法。
  • 这很有意义。谢谢。
  • @izex:我可以在您的个人资料中看到您尚未接受任何问题的答案。如果答案满足您的需求,请不要忘记接受它。欢迎来到!
  • 错了。这里的“匿名命名空间”效果完全被它在标题中的事实所击败。 #include 标头的任何实现文件都会将该名称空间的内容静态链接到其自身,从而获得匿名名称空间的内容。也就是说,你可以访问B,只说B而不是::B
【解决方案2】:

您只在全局命名空间中转发声明和交友的类 B。不是命名空间中的 B 类。您需要完全限定 B 的名称。

编辑:谢谢ereOn。
我犯了一个小错误。确实,您遇到问题的原因是因为您错误地声明和错误地引用了 B,但我最初的陈述并不完全正确。您需要将 B 从匿名命名空间中取出 - 无论如何,放在标题中是没有意义的。

【讨论】:

  • B 的名称已经是完全限定的 (::B) 但我猜 OP 只是意味着全局命名空间会产生一个空的命名空间。
【解决方案3】:

问题是您将B 称为::B 而不是B。意思是,你告诉编译器 B 是一个全局名称,但实际上它不是:它在一个匿名命名空间内。您不必删除匿名命名空间,只是它可能无法按照您的预期进行。因为匿名命名空间位于标头中,这意味着该命名空间中的内容静态链接到包含该标头的任何实现文件。这不是很有用,因为你什么也没有隐藏。您不妨删除该匿名命名空间。

【讨论】:

    【解决方案4】:

    你不能和你的构造函数交朋友吗?

    可以如下图所示

    struct B{
        B();
        void f();
    };
    
    struct A{
        friend B::B();
    private:
        A(){}
    };
    
    B::B(){A a;}       // fine
    
    void B::f(){A a;}  // error
    
    int main(){
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-24
      • 1970-01-01
      • 2019-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多