我正在尝试与一个类成为朋友,以便它能够访问它的私有构造函数。
在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)'是私有的。
我现在,这是私人的,这就是我成为朋友的原因。 我在这做错了什么? 你不能和你的构造者成为朋友吗? 是否存在名称空间问题?
由于
答案 0 :(得分:9)
这样做:
namespace {
class B {
protected:
A* get_a(int x) { return new A(x) };
}
}
您不是将B
放在根(全局)命名空间中,而是放在匿名命名空间中。
B
无法访问::B
。
如果您希望B
位于根(全局)命名空间中,则根本不要将其namespace
括起来。这应该可以解决问题。
答案 1 :(得分:1)
您只能在全局命名空间中转发声明和派生的B类。无论如何都不是命名空间中的B类。您需要完全限定B的名称。
编辑:谢谢你 我犯了一个小错误。确实,你遇到问题的原因是因为你错误地宣称并错误地提到了B,但我原来的说法并不完全正确。你需要把B从匿名命名空间中取出来 - 无论如何都是无题的。
答案 2 :(得分:0)
问题是您将B
称为::B
而不是B
。这意味着,你告诉编译器B
是一个全局名称,但事实上并非如此:它位于匿名命名空间内。您不必删除匿名命名空间,只是它可能无法执行您期望的操作。因为匿名命名空间位于标头中,所以它意味着该命名空间内部的内容静态链接到包含标头的任何实现文件。这不是很有用,因为你什么也没隐藏。您也可以删除该匿名命名空间。
答案 3 :(得分:0)
你不能和你的构造函数成为朋友吗?
您可以如下所示
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(){
}