派生类中隐藏的基类模板成员函数,尽管参数列表不同

Posted

技术标签:

【中文标题】派生类中隐藏的基类模板成员函数,尽管参数列表不同【英文标题】:Base class template member function shadowed in Derived class, albeit different parameter list 【发布时间】:2014-06-21 13:54:52 【问题描述】:

这让我很疑惑。假设我有:

class Base

public:

    template<typename T>
    void foo(T& varT)
    
        //
    

    template<typename T, typename U>
    void foo(T& varT, U& varU)
    
        //
    
;

class Child : public Base

public:
    template<typename T, typename U, typename Z>
    void foo(T& varT, U& varU, Z& varZ)
    
        //
    
;

现在当我尝试这个时:

Child c;

char cVar;
int iVar;
float fVar;

c.foo(cVar);
c.foo<int>(cVar);
c.template foo<int>(cVar);

所有调用都不起作用。它们总是被错误“没有匹配的调用成员函数”所掩盖。谁能指出我解决这个问题的方法?我在标准中读到派生对象影子模板函数继承,但标准明确指出,如果它们被影子,参数列表必须相同。

感谢您的帮助。

【问题讨论】:

“但标准明确规定,如果参数列表被遮蔽,则必须相同” 错误。这是覆盖虚函数所必需的。 【参考方案1】:

当您在派生类中有一个存在于基类中的名称时,总是会发生隐藏基成员的情况。基本原因是希望保护派生类的使用免受基类中的更改:假设基类中的名称没有隐藏,如果在基类中添加了新的重载,则可能会劫持派生成员的工作查找而是在派生类中没有任何指示基类中可能发生某些事情的情况下引用基类。如果您打算使基本成员可用,可以使用using 声明:

class Child : public Base

public:
     using Base::foo; // declare that you want look up members from the base class

     template<typename T, typename U, typename Z>
     void foo(T& varT, U& varU, Z& varZ)
     
         //
     
;

在您的代码中,您有三个调用:

    c.foo(cVar)using 声明一起使用。 c.foo&lt;int&gt;(cVar) 即使使用 using 声明也不起作用,因为您不能将非 const 引用绑定到 intchar 左值。使用 c.foo&lt;char&gt;(cVar) 可以。 c.template foo&lt;int&gt;(cVar) 也有同样的问题。由于c 显然不是从属名称,因此在这种情况下根本不需要使用template

如果没有 using 声明,您可以通过明确限定调用来调用成员,例如:

c.Base::foo(cVar);

【讨论】:

酷!感谢您的澄清。奇迹般有效。我会尽快接受这个答案:) @dyp:我改写了这句话(并添加了一些隐藏名称的理由)。 酷,在寻找模板方法是否可以覆盖其他模板方法时发现了这个 - 看起来他们可以,而且它做了理智的事情!【参考方案2】:

你需要这个: http://en.cppreference.com/w/cpp/language/using_declaration

添加到孩子的定义:

using Base::foo;

【讨论】:

以上是关于派生类中隐藏的基类模板成员函数,尽管参数列表不同的主要内容,如果未能解决你的问题,请参考以下文章

类成员函数的重载覆盖和隐藏

带有接受派生类参数的基类参数的成员函数指针

函数的重载重写与隐藏

在派生类中专门化模板成员

朋友类对象可以在其成员函数中访问派生类对象上的基类私有成员吗?

访问派生类中的基类成员