2012-01-27 9 views
7

これで、仮想関数の検索を避けるために、ここで修正された種類のCRTPを受け取ります。しかし、私はちょうど...テンプレート化された(静的な)メンバー関数から保護されたメンバーにアクセス

をそれは私を与えるつのエラーを理解することはできませんので、私は翻訳しようとしている:

に期待どおりに動作
class A 
{ 
public: 
    static void foo(A *pA) 
    { 
     pA->bar(); 
    } 

protected: 
    virtual void bar() 
    { 
     TRACE0(_T("A::bar\n")); 
    } 
}; 

class B : public A 
{ 
protected: 
    virtual void bar() 
    { 
     TRACE0(_T("B::bar\n")); 
    } 
}; 

与え
class A 
{ 
public: 
    template <class T> 
    static void foo(T *pT) 
    { 
     pT->bar(); 
    } 

protected: 
    void bar() 
    { 
     TRACE0(_T("A::bar\n")); 
    } 
}; 

class B : public A 
{ 
protected: 
    void bar() 
    { 
     TRACE0(_T("B::bar\n")); 
    } 
}; 

エラー:

error C2248: 'B::bar' : cannot access protected member declared in class 'B' 
see declaration of 'B::bar' 
see declaration of 'B' 
see reference to function template instantiation 'void A::foo<B>(T *)' 
being compiled with 
[ 
    T=B 
] 

は、今私は知っているが、これは簡単にクラスBにfriend class A;を追加することによって固定されているが、それはありません非常にきちんとした。別の方法はありませんか?

EDIT:使用例:

B b; 
b.foo<B>(&b); 

EDIT#2:メンバ関数foo私は気づいた問題ではありません静的であること。最初のケースbar

+0

これは、親クラスがchildernの保護されたメンバーに特別なアクセス権を持っていないためだと思います。子供が親にアクセスできるようにするだけです。 –

+1

Zanが言ったように、親クラスは派生クラスの保護されたメンバーにアクセスできません(もちろん友人でない限り) –

+0

右のような音がします... 'A :: foo'は' B :: bar'を呼び出そうとしています保護されているため失敗しています。 「友達クラスA」は適切な解決策のように聞こえる。 –

答えて

2

は、仮想関数であり、fooクラスAによってlayout'edようこうして関数ポインタとのVtableの指定されたインデックスを呼び出すAへのポインタを介してアクセスします。したがって、それは動作します。

ただし、2番目のケースでは、A::fooは、アクセス権のない別のクラスから非仮想関数を明示的に呼び出します。 B::barは、A::barという仮想オーバーロードではありません。無関係な機能はまったく異なります。

したがって、friend class A;を作ることは、あなたが得ることができる最も素敵です、私は恐れています。

関連する問題