繁体   English   中英

C ++模板朋友奇怪的行为

[英]C++ Template friend odd behavior

我在下面的代码中看到了一些我无法解释的内容。 在VS6,VS9和GCC T2 :: foo2()下给出错误:'bar':无法访问在类'C1'中声明的受保护成员。 但是如果你删除C1 :: bar(),它会编译并正确运行,即使T2仍在访问受保护的C1B:bar(),你会认为这是同样的问题。

注意,在T2 :: foo2()中,您可以将'pT1'转换为'T1 *'并且一切正常,但这仍然无法解释为什么允许C1B :: bar(),但C1 :: bar( ) 不是。

template<class S> class T2;

template<class T> class T1
{
    //template<class T> friend class T2;  --> this doesn't compile under VS6
    friend class T2<T>;

    protected:
        virtual void bar() { printf("T1\n"); }
};

template<class S> class T2
{
    public:
        void foo1(T1<S> *pT1) { pT1->bar(); }  // --> ok, makes sense, this works either way
        void foo2(S *pT1) { pT1->bar(); }  // --> this fails to compile if C1::bar() is defined, but works for C1B::foo() ???
};

class C1 : public T1<C1>
{
    protected:
        virtual void bar() { printf("C1\n"); }  // --> comment this out and foo2 will compile
};

class C1B : public  C1
{
    protected:
        virtual void bar() { printf("C1B\n"); }
};

class C2 : public  T2<C1>
{
};

void test(void)
{
    C1B c1b;
    C2 c2;
    c2.foo1(&c1b);
    c2.foo2(&c1b);  // --> fails to compile if C1::bar() exists
}

在您的示例中, foo2参数S的类型为C1 T2<S>T1<S>之间存在朋友关系。 虽然C1来自T1<C1>但它不会成为所有T1<C1>的朋友的朋友。

在表达式pT1->barbarC1找到,并且由于友谊不会传递给派生类,因此它是私有的。

您的例子是使用虚拟功能,因此这可以通过明确提到要解决bar 我们班的一个朋友:

void foo2(S *pT1) { pT1->template T1<S>::bar(); }

访问检查现在成功。

'03 C ++标准中的参考文献是11.4 / 10,它只是说:

友谊既不是遗传也不是传递。

感谢Potatoswatter的评论。 通过使用id-expessionqualified-id ,我们禁用虚拟调度(5.2.2 / 1):

如果所选函数是非虚拟的,或者类成员访问表达式中的id-expression是quali-ed-id,则调用该函数。

我们可以添加一个非虚拟调度程序,或者我们可以先将参数转换为基类型然后进行调用:

 void foo2(S *pT1) { static_cast< T1<S>* > (pT1)->bar(); }

现在可以根据需要进行虚拟调度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM