2017-08-29 84 views
2

我正在嘗試實現CRTP類的層次結構。我對基類能夠訪問一個派生類向下該鏈的數據成員:爲什麼不編譯以下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

雖然第一派生類(fromA)編譯和運行正如所料,該第二(fromB),從派生自A的類派生,不。

  1. 朋友聲明沒有引導到什麼原因?
  2. 有關解決方法的任何建議?
+0

爲什麼不創建虛函數getV()並在每個派生類中重寫它而不是與朋友的遊戲? –

+0

我朋友的'朋友'不是我在C++中的朋友。 – Jarod42

回答

4

問題是:我朋友的朋友不是我的朋友。

fromA你有

typedef A<fromA> base; 
friend base; 

這使得A<fromA>朋友和show可以訪問fromA的保護成員。

fromB你也有

typedef B<fromB> base; 
friend base; 

但是這並沒有使A的朋友,它使B你的朋友。即使A是B的朋友,但並不意味着它現在也是fromB的朋友,這就是爲什麼您不能訪問vshow。你能解決這個

的一種方法是,使公衆typedef A<Derived> base;B保護,然後在fromB你可以添加friend base::base;這將使A訪問。

+0

它的工作原理,謝謝!出於某種原因,我認爲'base'將它的結果一路鏈接到'fromB'。 –