5

我正在阅读 Balagurusamy ( http://highered.mcgraw-hill.com/sites/0070593620/information_center_view0/ ) 的 C++ 面向对象编程中的“本地类”概念。

最后一行说“封闭函数不能访问本地类的私有成员。但是,我们可以通过将封闭函数声明为友元来实现这一点。

现在我想知道如何完成突出显示的部分?

这是我正在尝试但没有运气的代码,

#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;
}

我知道代码看起来是错误的,任何帮助都会很明显。

4

4 回答 4

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 范围(仅限 C++)

所以,你运气不好。Balagurusamy 的提示仅适用于 MSVC 和类似的编译器。您可以尝试将执行移交给本地类中的静态方法作为解决方法:

int pqr() {
    class abc {
        int x;
    public:
        abc() : x(4) { }
        static int pqr() {
            return abc().x;
        }
    };
    return abc::pqr();
}
于 2010-07-13T08:18:05.407 回答
2

似乎对本地课程有误解。

通常在这里可以帮助您在函数内......并且不应该逃避函数的范围。

因此,函数不可能将其自己的本地类作为参数,该类从外部根本不可见。

另请注意,各种编译器(不幸地)不支持将这些本地类作为模板参数(例如 gcc 3.4),这实际上阻止了它们在 STL 算法中用作谓词。

使用示例:

int pqr()
{
   class foo
   {
     friend int pqr();
     int x;
     foo(): x() {}
   };

   return foo().x;
}

我必须承认,虽然我没有使用这么多,但考虑到我通常使用的受限范围struct而不是课堂,这意味着我不必担心交友;)

于 2010-07-13T08:39:32.123 回答
1

我还没有解决朋友问题的方法(甚至不知道是否可以完成),但请阅读以了解有关本地课程的更多信息。这将告诉您,您不能在定义它们的函数之外使用本地类(正如@In silico在他的回答中指出的那样。)

编辑这似乎不可能,因为这篇文章解释说:

在友元声明中首次引入的函数的名称位于包含封闭类的第一个非类范围的范围内。

换句话说,本地类只有在其封闭函数中声明时才能与函数成为朋友。

于 2010-07-13T08:35:19.750 回答
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; 
}

这在 Visual C++(编译器版本 15.00.30729.01)上编译时没有警告。

于 2010-07-13T08:06:40.430 回答