朋友类声明和使用指令

问题描述:

以下示例是否格式良好?朋友类声明和使用指令

namespace N { 
    class A; 
} 
using namespace N; 

class B { 
    int i; 
    friend class A; 
}; 

namespace N { 
    class A { 
     B m; 
     int get() { return m.i; } 
    }; 
} 

该实施例与锵3.5编译成功,但未能与克++ 4.8.1具有以下:

main.cpp: In member function ‘int N::A::get()’: 
main.cpp:7:9: error: ‘int B::i’ is private 
    int i; 
     ^
main.cpp:14:30: error: within this context 
     int get() { return m.i; } 
          ^

C++ 11标准§7.3.1.2P3表示,

如果friend声明中的名称既不合格,也不是模板标识,并且该声明是函数或详细描述类型说明r,用于确定实体是否先前已被声明的查找不应考虑在最内部的封闭名称空间之外的任何作用域。

在示例,class A不是构件最内侧包围命名空间(即全局命名空间),但class A,通过使用指令到全局命名空间引入。

+0

由于'using namespace N',你正在N内创建一个嵌套的命名空间'N',尝试删除最后一个'namespace N' –

+3

@ichramm:嗯,真的吗? –

+2

@ichramm'using namespace N'并不意味着后面的所有内容都隐含属于'namespace N' – Praetorian

使用名称空间N将名称N :: A拉入全局名称空间时,它并不是在全局名称空间中声明该名称。因此,全局命名空间中的另一个A是B. clang的朋友是错误的。

+0

@Diether C++ 11 standard 7.3.4 p2说:“在非限定名称查找(3.4.1)期间,名称显示为**,好像它们被声明为...”,3.4.1 p2表示“对于3.4.1中描述的非限定名称查找规则的用途,* using-directive * **提名的命名空间中的声明被视为该封闭名称空间**的成员。 –

+1

@Diether:谢谢!你很对!我发现问题[N1229](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2000/n1229.html)。不过,我认为C++ 11标准应该更清楚地表明这种情况。 –

为了N::A没有资格B一个friend你会使用

friend A; 

而不是

friend class A; 

当使用精细的类型说明符,即class A,它是在这个特定的形式,它引入了一个类名(见3.4.4 [basic.lookup.elab]第2段)。

+0

[basic.lookup.elab]/2中提到的表单不包含“friend”,据我所知。所以这里提到的形式是朋友声明的一部分。它仍然适用? – dyp

+0

@dyp:是的,我知道。然而,'friend class A;'_does_匹配表达式“。* _class-key attribute-specifier-seq?identifier; _”。我认为它的目的是将它与'class foo f();'或'int stat(struct stat *)'等用法区分开来,我认为它也适用。 –