25

以下のサンプルコードを参照してください。

class A
{
private:
    class B
    {
    public:
        foobar();
    };
public:
    foo();
    bar();
};

クラスAおよびBの実装内:

A::foo()
{
    //do something
}

A::bar()
{
    //some code
    foo();
    //more code
}

A::B::foobar()
{
    //some code
    foo(); //<<compiler doesn't like this
}

コンパイラーは、メソッドfoobar()内のfoo()の呼び出しにフラグを立てます。以前、私はfoo()をクラスAのプライベートメンバー関数として持っていましたが、Bの関数がそれを見ることができないと仮定してpublicに変更しました。もちろん、それは役に立ちませんでした。Aの方法で提供される機能を再利用しようとしています。コンパイラがこの関数呼び出しを許可しないのはなぜですか?私が見るように、それらは同じ囲みクラス(A)の一部です。クラスをC++標準で囲むためのネストされたクラスmeebersのアクセシビリティの問題は解決されたと思いました。

BをA内にネストしたままにするBの同じメソッド(foo())を書き直さずに、私がやろうとしていることをどのように達成できますか?

VC ++コンパイラver-9(Visual Studio 2008)を使用しています。ご協力ありがとうございました。

4

5 に答える 5

28

foo()の非静的メンバー関数でAあり、インスタンスなしで呼び出そうとしています。
ネストされたクラスBは、一部のアクセス権限のみを持ち、 の既存のインスタンスに関する特別な知識を持たない別のクラスですA

Bへのアクセスが必要な場合はA、それへの参照を与える必要があります。

class A {
    class B {
        A& parent_;
    public:
        B(A& parent) : parent_(parent) {}
        void foobar() { parent_.foo(); }
    };
    B b_;
public:
    A() : b_(*this) {}
};
于 2010-06-17T01:33:28.373 に答える
2

これはオートマジックですが、移植性のないトリックである可能性があります(ただし、6.0以降はVC ++で機能します)。これが機能するには、クラスBがクラスAのメンバーである必要があります。

#ifndef OUTERCLASS
#define OUTERCLASS(className, memberName) \
    reinterpret_cast<className*>(reinterpret_cast<unsigned char*>(this) - offsetof(className, memberName))
#endif 

class A
{
private:
    class B
    {
    public:
        void foobar() {
           A* pA = OUTERCLASS(A, m_classB);
           pA->foo();
        }
    } m_classB;
public:
    foo();
    bar();
};
于 2010-06-17T01:42:28.330 に答える
1

基本的にゲオルク・フリッチェが言ったこと

#include <iostream>
#include <cstring>
using namespace std;

class A
{
private:
    class B
    {
     A& parent_;
     public:
        //B();  //uncommenting gives error
        ~B();
        B(A& parent) : parent_(parent) {}

        void foobar() 
        { 
         parent_.foo();  
         cout << "A::B::foo()" <<endl; 
        }

        const std::string& foobarstring(const std::string& test) const 
        { 
         parent_.foostring(test); cout << "A::B::foostring()" <<endl;
        }
    };
public:
    void foo();
    void bar();
    const std::string& foostring(const std::string& test) const;
    A(); 
    ~A(){};
    B b_;
};

//A::B::B() {}; //uncommenting gives error
A::B::~B(){};

A::A():b_(*this) {}


void A::foo()
{
    cout << "A::foo()" <<endl;
}

const std::string& A::foostring(const std::string& test) const
{
    cout << test <<endl;
    return test;
}

void A::bar()
{
    //some code
    cout << "A::bar()" <<endl;
    foo();
    //more code
}

int main(int argc, char* argv[])
{
A a;
a.b_.foobar();
a.b_.foobarstring("hello");

return 0;
}

デフォルトの B コンストラクターのコメントを外すと、エラーが発生します

于 2012-05-15T19:22:44.663 に答える
0

A の機能を再利用したい場合は、A から継承し、B を入れ子にする必要はありません。

于 2010-06-17T01:16:11.523 に答える