为什么我不能从 C 中的派生类实例调用模板化方法?

发布于 2024-11-07 22:36:07 字数 608 浏览 0 评论 0原文

请考虑这些类型:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陈年往事 2024-11-14 22:36:07

您面临的问题称为隐藏。基本上,语言中的查找规则将从最派生的类型开始,然后向上返回,直到找到适当的符号。在您的情况下,它会在查看 B 类时停止,因为它发现 void B::foo(const std::string& name)。在这一级别上,它会考虑的唯一潜在过载就是它所看到的过载。

为了避免隐藏,您可以引入所有其他重载,您可以添加 using 声明:

struct B : A{
   using A::foo;
   void foo( const std::string & name );
};

不同之处在于查找将沿层次结构进行查找,直到找到第一个重载,该重载又位于 B< /code> 级别,但由于 using 指令,它还会考虑 A 中可用的任何重载。

或者,您可以隐藏符号并通过限定调用强制分派到确切的类(请注意,这会产生禁用动态分派的副作用,这在这里不是问题,但如果要使用的重载是虚拟的,则可能会出现问题) :

b->A::foo<X>();

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 finds void 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:

struct B : A{
   using A::foo;
   void foo( const std::string & name );
};

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 the using directive, it will also consider any overload available in A.

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):

b->A::foo<X>();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文