2017-08-29 23 views
2

私はCRTPクラスの階層を実装しようとしています。 、第予想通り第一派生クラス(fromA)をコンパイルし、実行が次のCRTP階層がコンパイルされないのはなぜですか?

#include <iostream> 

template <class Derived> 
class A { 
public: 
    void showv() { 
     std::cout << static_cast<const Derived*>(this)->v << std::endl; 
    } 
}; 

template <class Derived> 
class B : public A<Derived> { 
    typedef A<Derived> base; 
    friend base; 
}; 

class fromA : public A<fromA> { 
    typedef A<fromA> base; 
    friend base; 
protected: 
    int v = 1; 
}; 

class fromB : public B<fromB> 
{ 
    typedef B<fromB> base; 
    friend base; 
protected: 
    int v = 2; 
}; 

int main() 
{ 
    // This runs ok 
    fromA derived_from_a; 
    derived_from_a.showv(); 

    // Why doesn't the following compile and complains about the protected member? 
    fromB derived_from_b; 
    derived_from_b.showv(); 

    return 0; 
} 

Demo

:私はチェーンダウン派生クラスのデータメンバにアクセスできるように、基本クラスに興味(fromB)、これはAから派生したクラスに由来します。

  1. フレンド宣言が配信されない理由は何ですか?
  2. 回避策についてのご意見はありますか?
+0

なぜ、仮想関数getV()を作成してお友達とのゲームの代わりに、それぞれの派生クラスでオーバーライドしないのですか? –

+0

私の 'friend'の' friend'はC++の私の友達ではありません。 – Jarod42

答えて

4

問題は次のとおりです。私の友人の友人は私の友人ではありません。 fromA

あなたはfromA年代protectedメンバにアクセスすることができA<fromA>友人とshowを作る

typedef A<fromA> base; 
friend base; 

持っています。 fromB

あなたも

typedef B<fromB> base; 
friend base; 

を持っている。しかし、これはA友人をしない、それがBあなたの友人を作ります。 AがBの友人であっても、現在はfromBの友人であることを意味しないため、vshowという名前でアクセスすることはできません。あなたはこの問題を解決することができ

一つの方法は、typedef A<Derived> base;は、パブリックまたはBで保護され、その後fromBであなたがAアクセス権を与えるだろうfriend base::base;を追加できるようにすることです。

+0

それは、ありがとう!何らかの理由で、私は 'base'が結果を' fromB'まで連鎖していると考えました。 –

関連する問題