为什么以下CRTP层次结构无法编译?

时间:2017-08-29 17:32:40

标签: c++ polymorphism hierarchy friend 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. 有关解决方法的任何建议吗?

1 个答案:

答案 0 :(得分:4)

问题是:我朋友的朋友不是我的朋友。

fromA你有

typedef A<fromA> base;
friend base;

使A<fromA>成为朋友,show可以访问fromA的受保护成员。

fromB你还有

typedef B<fromB> base;
friend base;

但这并不能使A成为朋友,而是让B成为你的朋友。即使A是B的朋友,但这并不意味着它现在也是fromB的朋友,这就是您无法访问v中的show的原因。

解决此问题的一种方法是在typedef A<Derived> base;中公开或保护B,然后在fromB中添加friend base::base;,这将A访问。