从模板(静态)成员函数访问受保护的成员

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;可以轻松解决此问题,但这并不是很简洁。还有其他方法吗?
编辑:示例用法:
B b;
b.foo<B>(&b);

编辑 #2:我注意到成员函数foo是静态的并不重要。

我认为这是因为父类没有特殊访问子类的受保护成员(难道有吗?)。只有子类可以访问父类。 - Zan Lynx
1
正如Zan所说,父类不能访问派生类的受保护成员(除非它是友元)。 - Seth Carnegie
听起来没错... A::foo 试图调用 B::bar,但由于其受保护,失败了。friend class A 听起来是正确的解决方案。 - Mark Ransom
所以在第一种情况下,似乎只有父类可以访问派生类的受保护成员,因为它调用了一个虚函数(自己类的),而该函数“向上查询”到派生类? - demorge
是的,它能够工作是因为它是一个虚函数。 - Eric Fortin
1个回答

2
在第一种情况下,bar 是虚函数,foo 通过指向 A 的指针访问它,从而调用函数指针和由类 A 布局的指定索引的 Vtable。因此,它可以工作。
然而,在第二种情况下,A::foo 显式调用了来自不同类的非虚函数,它无法访问。 B::bar 不是 A::bar 的虚重载 - 它是完全不相关的函数。
因此,我恐怕只能做到最好的方法是使 friend class A;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接