11

次の例のコンパイル:

class A
{
  public:
    void foo()
    {
    }
};

class B : private A
{
  public:
    using A::foo;
};

int main()
{
    typedef void (B::*mf)();
    mf func = &B::foo;

    B b;
    (b.*func)();
}

次のエラーで失敗します:

main.cpp||In function ‘int main()’:  
main.cpp|18|error: ‘A’ is an inaccessible base of ‘B’  
main.cpp|18|error:    in pointer to member function conversion

AはBのアクセス可能なベースではないことを理解していますが、usingキーワードを使用しています。関数fooへのアクセスを許可するべきではありませんか?

上記のコンパイルを妨げる規格の関連する段落は何ですか?

4

3 に答える 3

6

fooinBは、から継承されているためA&B::fooと同じで&A::foo、タイプはvoid (A::*)()です。あなたが書くとき

typedef void (B::*mf)();
mf func = &B::foo;

void (A::*)()からに変換しようとしていvoid (B::*)()ます。Bあなたから個人的に継承するので、それをA行うことはできません。

于 2011-09-15T08:38:22.230 に答える
3

のメンバーへのアクセスAは第11章「メンバーアクセス制御」によって管理されますが、ポインターからメンバーへの変換は4.11でカバーされています。特に、4.11 / 2は、をに変換できない場合、T A::*をに変換できないことを示しています。T B::*B*A*

質問のわずかなバリエーションを次に示します。

class A
{
  public:
    void foo()
    {
    }
};

class B : private A
{
  public:
    using A::foo;
};

int main()
{
    typedef void (A::*amf)();
    typedef void (B::*bmf)();
    amf func = &A::foo;
    bmf f2 = static_cast<bmf>(func);
}

私たちはまだ同じ機能について話している。B::foo失敗するのは名前の検索ではなく(それを処理します)、のタイプはに変換できないusingという事実です。B::foovoid A::*()void B::*()

于 2011-09-15T08:41:49.340 に答える
-1

問題を単純化しました。主な問題は以下のとおりです。

int main() 
{ 
    &B::foo; 
}

ここでは、クラスAで定義され、プライベートに継承されているfooのアドレスにアクセスしようとしています。したがって、コンパイルエラーが発生します。

を使用すると、関数がインポートされます。fooのアクセス指定子は変更されません。

于 2011-09-15T11:35:38.573 に答える