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

Posted

技术标签:

【中文标题】在模板函数中调用继承的方法【英文标题】:Call inherited method inside template function 【发布时间】:2014-11-11 14:35:05 【问题描述】:

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

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
    

;

这最终导致编译器错误:

error C2352: 'A::someMethod' : 非法调用非静态成员函数

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

【问题讨论】:

这违反了继承规则。您的 B 类没有模板 someMethod()。当您说templateMethod&lt;B&gt;(); 时,您正在尝试使用从 A 类继承的 templateMethod() A 不继承自 BC 并且不能在对象的上下文中直接调用它们的非静态成员函数。您需要将指针传递给templateMethod 或重新考虑您的实现。 有趣的是,这个代码示例在 clang++ 3.4 中编译得非常好。 【参考方案1】:

template &lt;TBaseClass&gt; void A::templateMethod() 中,调用者this 的类型为A *。所以当你尝试在它上面调用B::someMethod时,编译器不会把它识别为对象方法调用,因为B不是基类,但它仍然可以是静态方法调用,所以编译器会尝试,找到通过A 继承的B::someMethod 并抱怨它不是静态的。 Athis 的基类这一事实不相关;只有B 不是。

【讨论】:

【参考方案2】:

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

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

template <class TBaseClass>
void templateMethod()

    static_cast<TBaseClass*>(this)->someMethod();

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

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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于在模板函数中调用继承的方法的主要内容,如果未能解决你的问题,请参考以下文章

模板……基础知识笔记

C++提高编程

C++提高编程模板 or 泛型

c++重用和模板

c++模板--让偷懒成为常态

c++模板--让偷懒成为常态