我正在阅读使用C ++的面向对象编程中的“本地类”概念作者:Balagurusamy(http://highered.mcgraw-hill.com/sites/0070593620/information_center_view0/)。
最后一行说“封闭函数无法访问本地类的私有成员。但是,我们可以通过将封闭函数声明为朋友来实现此目的。”
现在我想知道突出显示的部分是如何完成的?
这是我尝试的代码,但没有运气,
#include<iostream>
using namespace std;
class abc;
int pqr(abc t)
{
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
我知道代码看起来很错误,任何帮助都会很明显。
答案 0 :(得分:3)
您的friend
声明没问题。
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
friend int pqr();
};
return abc().x;
}
int main() {
cout << "Return " << pqr() << endl;
}
修改:
IBM为评论中提出的问题提供了这种解释:
如果您在本地类中声明了一个朋友,并且该朋友的名称是不合格的,则编译器将仅在最内层的非类作用域内查找该名称。 [...]你没必要上课。
void a();
void f() {
class A {
// error: friend declaration 'void a()' in local class without prior decl...
friend void a();
};
}
friend void a():此语句不考虑在命名空间作用域中声明的函数a()。由于函数a()尚未在f()的范围内声明,因此编译器不允许使用此语句。
来源:IBM - Friend scope (C++ only)
所以,你运气不好。 Balagurusamy的提示仅适用于MSVC和类似的编译器。您可以尝试将执行切换到本地类中的静态方法作为解决方法:
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
static int pqr() {
return abc().x;
}
};
return abc::pqr();
}
答案 1 :(得分:2)
似乎对当地的课程存在误解。
通常这里有帮助你在函数内...并且不应该逃避函数的范围。
因此,函数不可能将自己的本地类作为参数,该类从外部看不到。
另请注意,各种编译器(不幸的是)不支持这些本地类作为模板参数(例如gcc 3.4),这实际上阻止了它们在STL算法中用作谓词。
使用示例:
int pqr()
{
class foo
{
friend int pqr();
int x;
foo(): x() {}
};
return foo().x;
}
我必须承认,虽然我不使用这么多,但考虑到范围受限,我通常使用struct
代替课程,这意味着我不必担心朋友;)
答案 2 :(得分:1)
我还没有朋友的解决方案(甚至不知道是否可以完成),但请阅读this和this以了解更多有关本地课程的信息。这将告诉您不能在其定义的函数之外使用本地类(如In silico中指出@ answer。)
编辑这似乎不可能,正如this文章所解释的那样:
首先在友元声明中引入的函数的名称在包含封闭类的第一个非类作用域的范围内。
换句话说,如果函数在其封闭函数中声明,则本地类只能与函数成为一个函数。
答案 3 :(得分:0)
friend int pqr(abc);
声明没问题。它不起作用,因为在abc
函数中将pqr()
类型用作参数类型之前尚未定义#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// Class defined outside the pqr() function.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
// At this point, the compiler knows what abc is.
int pqr(abc t)
{
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
类型。在函数之前定义它:
abc
我知道您想使用本地课程,但您所设置的课程将无效。本地类仅在其定义的函数内可见。如果要在pqr()
函数之外使用abc
的实例,则必须在函数外部定义abc
类。
但是,如果您知道pqr()
类仅在friend
函数中使用,则可以使用本地类。但在这种情况下,您确实需要稍微修复#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// pqr() function defined at global scope
int pqr()
{
// This class visible only within the pqr() function,
// because it is a local class.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
// Refer to the pqr() function defined at global scope
friend int ::pqr(); // <-- Note :: operator
} t;
t.xyz();
return t.x;
}
int main()
{
cout<<"Return "<<pqr()<<endl;
}
声明。
{{1}}
在Visual C ++(编译器的15.00.30729.01版)上编译没有警告。