在模板函数中调用继承的方法
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<B>();
时,您正在尝试使用从 A 类继承的 templateMethod()
A
不继承自 B
或 C
并且不能在对象的上下文中直接调用它们的非静态成员函数。您需要将指针传递给templateMethod
或重新考虑您的实现。
有趣的是,这个代码示例在 clang++ 3.4 中编译得非常好。
【参考方案1】:
在template <TBaseClass> void A::templateMethod()
中,调用者this
的类型为A *
。所以当你尝试在它上面调用B::someMethod
时,编译器不会把它识别为对象方法调用,因为B
不是基类,但它仍然可以是静态方法调用,所以编译器会尝试,找到通过A
继承的B::someMethod
并抱怨它不是静态的。 A
是 this
的基类这一事实不相关;只有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 不会起作用的原因。
【讨论】:
以上是关于在模板函数中调用继承的方法的主要内容,如果未能解决你的问题,请参考以下文章