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

Access protected members from templated (static) member function

本文关键字:成员 函数 访问 受保护 静态      更新时间:2023-10-16

好的,所以我在这里采用了一种修改后的CRTP路由,以避免虚拟函数查找。但我就是不能理解它给我的一个错误…

所以我试着翻译:

class A
{
public:
    static void foo(A *pA)
    {
        pA->bar();
    }
protected:
    virtual void bar()
    {
        TRACE0(_T("A::barn"));
    }
};
class B : public A
{
protected:
    virtual void bar()
    {
        TRACE0(_T("B::barn"));
    }
};

如预期的那样工作:

class A
{
public:
    template <class T>
    static void foo(T *pT)
    {
        pT->bar();
    }
protected:
    void bar()
    {
        TRACE0(_T("A::barn"));
    }
};
class B : public A
{
protected:
    void bar()
    {
        TRACE0(_T("B::barn"));
    }
};

给出错误:

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
]

现在我知道了,通过将friend class A;添加到类B中可以很容易地解决这个问题,但这不是很好。难道没有别的办法吗?

EDIT:示例用法:

B b;
b.foo<B>(&b);

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

在第一种情况下,bar是虚拟函数,foo通过指向A的指针访问它,从而调用函数指针和指定的Vtable索引作为类A的布局。这样它就起作用了。

然而,在第二种情况下,A::foo从它无法访问的不同类显式调用非虚拟函数。B::bar不是A::bar的虚拟重载,它是完全不同的无关函数。

因此,恐怕制作friend class A;是你能得到的最整洁的。