受保护的依赖模板库成员

时间:2018-06-04 02:15:03

标签: c++ templates

所以我已经阅读了this个问题,并且我理解了模板中依赖名称的前提,以及如何有时必须使用this->限定方法以确保编译器能够正确找到它,但是我遇到了一个我无法弄清楚如何解决的场景。具体来说,当方法所属的对象与*this属于同一类型时,它是一个不同的对象(可能是不同的子类)。例如:

#include <iostream>

template<class T>
class A
{
protected:
    virtual void foo() = 0;
};

template<class T>
class B : public A<T>
{
};

template<class T>
class C : public B<T>
{
protected:
    void foo() override
    {
        std::cout << "Hello, world" << std::endl;
    }
};

template<class T>
class D : public B<T>
{
protected:
    void foo() override
    {
        B<T> *b = new C<T>();
        b->foo(); // error: 'void A<T>::foo() [with T = int]' is protected
    }
public:
    void bar()
    {
        this->foo();
    }
};

int main()
{
  D<int> d;
  d.bar();
}

考虑到这个继承层次结构,以及调用b->foo();时的错误,调用该函数的正确方法是什么?据我所知,D中的代码原则上应该是可访问的,因为它是基类的受保护成员,但模板系统使它复杂化。

1 个答案:

答案 0 :(得分:2)

您的问题与模板无关,如果删除所有模板代码,则会出现相同的错误。

将成员声明为protected意味着您只能从同一个(直接)类访问该成员;因此,虽然DC可能B派生,但它们都是明显不同的类型,而不是直接 a {{1因此,BD无法访问C的另一个实例的受保护成员。

例如,使用您发布的一些代码获取以下代码:

B

在您的代码中,在class D : public B { public: void baz(D& d, B& b) { foo(); // ok: calls this->foo(); d.foo(); // ok: type of `d` is `D`, same class b.foo(); // error: can't access protected member } }; 类中将B* b = new C();更改为B* b = new B();仍会在尝试访问受保护的成员时遇到同样的错误。如果您将其更改为D,则错误会消失,因为D* b = new D();现在与其所在的类型相同。

要解决此错误,您可以声明bD的朋友,但这会引入其他需要考虑的问题,您还必须为所需的每个课程添加转发/好友声明以这种方式访问​​B

foo

但是,根据您发布的代码,我们倾向于将template < class T > class D; template <class T> class B : public A<T> { friend class D<T>; }; 功能移出bar并将其放入D,然后您不要&# 39;必须使用前向声明进行清理,并且大多数代码保持不变:

B

这可能不适合您的特定情况,但最终您的问题基本上归结为需要template <class T> class B : public A<T> { public: void bar() { this->foo(); } }; // Then in your D class, change the call from `foo` to `bar` template <class T> class D : public B<T> { protected: void foo() override { B<T> *b = new C<T>(); b->bar(); } }; 访问权限。

希望可以提供帮助。