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

时间:2014-11-11 14:35:06

标签: c++ templates inheritance

我在父类中有一个模板方法,它应该从基类调用另一个方法。如果方法在基类中明确定义,它可以工作,但如果方法是继承的,它就不起作用。我无法弄清楚这段代码究竟有什么问题(虽然我知道这有点奇怪:)

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:&#39; A :: someMethod&#39; :非静态成员函数的非法调用

究竟出了什么问题?我不是在寻找变通方法,这很容易。我想知道为什么这不正确。

3 个答案:

答案 0 :(得分:1)

template <TBaseClass> void A::templateMethod() this中,调用者A *的类型为B::someMethod。因此,当您尝试在其上调用B时,编译器不会将其识别为对象方法调用,因为B::someMethod不是基类,但它仍然可以是静态方法调用,所以编译器会尝试这一点,找到通过A继承的A并抱怨它不是静态的。 thisB的基类这一事实并不重要;仅{{1}}不是。

答案 1 :(得分:0)

我认为它不起作用,因为你试图调用静态方法。 静态方法可以继承,但不能是虚拟的。 这就是为什么A :: someMethod会起作用而B :: someMethod不会起作用。

答案 2 :(得分:0)

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

要执行您正在尝试的操作,您需要将A强制转换为目标类型:

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

如果您正在调用的A的特定实例确实是B(在您给出的示例中),这将起作用。这里没有进行类型检查以确保它是。如果传递的类不在继承层次结构中,那么您将处于未定义行为的工作中。

那就是说,你的例子将“someMethod()”视为虚拟。如果你正在做我刚才做的事情,那么将该方法设为虚拟可能没有意义,因为你明确地说明了你想要的实例。如果你把它保留为虚拟,那么直接在A中调用someMethod()将获得最多派生的实例。