为什么我不能从 C 中的派生类实例调用模板化方法?
请考虑这些类型:
struct X
{
static std::string fullyQualifiedName();
};
struct A
{
template <class T> void foo()
{
return foo(T::fullyQualifiedName());
}
protected:
virtual void foo(const std::string& name) = 0;
};
struct B : public A
{
protected:
void foo(const std::string& name);
};
我有一个指向 B 实例的指针,我正在尝试调用 foo
的模板化版本,如下所示:
b->foo< X >();
编译器抱怨:“X”:非法使用此类型作为一种表达方式。
另一方面,这段代码完全没问题:
A* a = b;
a->foo< X >();
这就是我的问题。
Please consider these types:
struct X
{
static std::string fullyQualifiedName();
};
struct A
{
template <class T> void foo()
{
return foo(T::fullyQualifiedName());
}
protected:
virtual void foo(const std::string& name) = 0;
};
struct B : public A
{
protected:
void foo(const std::string& name);
};
I have a pointer to an instance of B, I'm trying to invoke the templated version of foo
like so:
b->foo< X >();
The compiler is complaining: 'X' : illegal use of this type as an expression.
On the other hand, this code's perfectly ok:
A* a = b;
a->foo< X >();
Hence my question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您面临的问题称为隐藏。基本上,语言中的查找规则将从最派生的类型开始,然后向上返回,直到找到适当的符号。在您的情况下,它会在查看
B
类时停止,因为它发现void B::foo(const std::string& name)
。在这一级别上,它会考虑的唯一潜在过载就是它所看到的过载。为了避免隐藏,您可以引入所有其他重载,您可以添加
using
声明:不同之处在于查找将沿层次结构进行查找,直到找到第一个重载,该重载又位于
B< /code> 级别,但由于
using
指令,它还会考虑A
中可用的任何重载。或者,您可以隐藏符号并通过限定调用强制分派到确切的类(请注意,这会产生禁用动态分派的副作用,这在这里不是问题,但如果要使用的重载是虚拟的,则可能会出现问题) :
The problem you are facing is called hiding. Basically the lookup rules in the language will start in the most derived type and work their way back up until it finds the appropriate symbol. In your case it will stop while looking at the
B
class as it findsvoid B::foo(const std::string& name)
. At that level, the only potential overload that it will consider is the one it is seeing.To avoid hiding you can bring all the other overloads you can add a
using
declaration:The difference is that lookup will work up the hierarchy until it finds the first overload, which is again at
B
level, but because of theusing
directive, it will also consider any overload available inA
.Alternatively, you can leave the symbol hidden and force dispatch to the exact class by qualifying the call (note that this has the side effect of disabling dynamic dispatch, which is not a problem here, but could be if the overload to use is virtual):