5

BalagurusamyによるC++によるオブジェクト指向プログラミングの「ローカルクラス」の概念を読んでいます(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;
}

私はコードが間違っているように見えることを知っています。

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-フレンドスコープ(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) としてサポートしていないことにも注意してください。

使用例:

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 に答える