调用模板函数内部的继承方法

Call inherited method inside template function

本文关键字:继承 方法 内部 函数 调用      更新时间:2023-10-16

我在父类中有一个模板方法,它应该从基类调用另一个方法。如果方法是在基类中显式定义的,那么它是有效的,但如果方法是继承的,那么就不起作用。我不知道这个代码到底出了什么问题(尽管我知道这有点奇怪:)

class A
{
protected:
    virtual void someMethod() 
    {
    }
    template <class TBaseClass>
    void templateMethod()
    {
        TBaseClass::someMethod();
    }
};
class B : public A 
{   
};
class C : public B
{
protected:
    virtual void someMethod()
    {
        templateMethod<A>(); // this works
        templateMethod<B>(); // this doesn't
    }
};

这最终导致编译器错误:

错误C2352:"A::someMethod":非法调用非静态成员函数

到底出了什么问题?我不是在找变通办法,这很容易。我想知道为什么这是不正确的。

template <TBaseClass> void A::templateMethod()中,调用程序this的类型为A *。因此,当你试图对它调用B::someMethod时,编译器不会将其识别为对象方法调用,因为B不是基类,但它仍然可以是静态方法调用,所以编译器会尝试,找到通过A继承的B::someMethod,并抱怨它不是静态的。Athis的基类这一事实并不相关;只是CCD_ 10不是。

问题是类A没有自动被授予对类B的访问权限。类中的方法不知道A的当前实例实际上是B类型的。

要做你正在尝试的事情,你需要将A投射到目标类型:

template <class TBaseClass>
void templateMethod()
{
    static_cast<TBaseClass*>(this)->someMethod();
}

如果你调用的A的特定实例真的是B(就像你给出的例子一样),这将起作用。这里没有进行类型检查来确保它是。如果你传递的类不在继承层次结构中,你将处于未定义行为的工作中。

也就是说,您的示例具有虚拟的"someMethod()"。如果你正在做我刚才在这里做的事情,那么将该方法虚拟化可能没有意义,因为你明确地说你想要哪个实例。如果您确实将其保留为虚拟实例,那么只需直接在A中调用someMethod()就可以获得最派生的实例。

我认为它不起作用,因为您正试图调用一个静态方法。静态方法可以继承,但不能是虚拟的。这就是为什么A::someMethod有效,B::someMethod无效的原因。