ネストされたクラスメンバー関数は、囲まれたクラスの関数にアクセスできません。なんで?
-
27-09-2019 - |
質問
以下のサンプルコードを参照してください。
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()への呼び出しにフラグを立てます。以前、私はクラスAのプライベートメンバー関数としてfoo()を持っていましたが、Bの関数がそれを見ることができないと仮定して一般に変更されました。もちろん、それは助けにはなりませんでした。 Aの方法で提供される機能を再利用しようとしています。コンパイラがこの関数呼び出しを許可しないのはなぜですか?私が見るように、それらは同じ囲いのクラス(a)の一部です。 C ++標準でクラスを囲むためのネストされたクラスのミーバーのアクセシビリティの問題は解決されたと思いました。
Bの同じ方法(foo())を書き直さずに自分がやろうとしていることを達成するにはどうすればよいですか?
VC ++コンパイラVER-9を使用しています(Visual Studio 2008)。ご協力ありがとうございました。
解決
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) {}
};
他のヒント
これは、おそらくポルトできないトリックではありますが、自動車です(ただし、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();
};
Aから機能を再利用したい場合は、その中の巣のないbから継承する必要があります。
基本的に、ゲオルグ・フリッツシュが言ったこと
#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コンストラクターを外すと、エラーが発生します