2012-01-27 116 views
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 
] 

现在我知道,这是很容易通过添加friend class A; B类固定的,但是这不是 井井有条。没有其他办法吗?

编辑:实例:

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

EDIT#2:该成员函数foo是静止不要紧我注意到。

+0

我认为这是因为父类没有特殊的访问childern的保护成员(他们?)。它只适用于儿童有权访问父母。 – 2012-01-27 20:30:16

+1

正如Zan所说,父类不能访问派生类的受保护成员(除非它是朋友) – 2012-01-27 20:31:32

+0

关于正确的声音......'A :: foo'试图调用'B :: bar'并因其受到保护而失败。 “A级朋友”听起来像是正确的解决方案。 – 2012-01-27 20:33:36

回答

2

在第一种情况是bar虚函数和foo访问它通过一个指向A从而调用函数指针和V表的指定索引由A类作为layout'ed。因此它起作用。

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

因此,制作friend class A;是最恐怖的事情。