4

我正在开发一个库,我设计了一个复杂的继承,其中包括模板类并从它们派生。我的问题是一个基模板类具有虚拟重载运算符,它接受 2 个参数并返回一些值。在基类中实现了这个操作符,大多数派生类没有重新实现这个操作符。

其他一些类将派生类用于某些工作并利用它们的操作员成员函数。只要派生类没有其他重载运算符,即使参数数量不同,一切都可以正常工作。如果这样做,则无法使用它访问基类运算符,object()因为编译器找不到正确的成员函数(抱怨参数计数不匹配)。

是否指定了基类的默认模板参数并不重要。派生类的定义顺序也不会改变导致问题的运算符(它始终是SpecificDerived类)。

下面我提出简化的问题。

[编辑] 示例已简化

基类定义:

template<class ret_t>
class TemplateBase2
{
public:
    virtual ~TemplateBase2()
    {
    }

    virtual ret_t memberFunc(ret_t x)
    {
        return x * 2;
    }
};

派生类定义的用户:

template <class worker, class ret_t>
ret_t gobble(worker w, float f)
{
    return w.memberFunc((ret_t)f);
}

派生类:

class SpecificDerived2: public TemplateBase2<float>
{
public:
    float memberFunc()
    {
        return 3.14;
    }
};

主功能:

#include <iostream>
#include "TemplateBase2.h"

using namespace std;

int main()
{
    SpecificDerived2 sd2;

    cout << "sd2: " << gobble<SpecificDerived2, float>(sd2, 3.14f) << endl; 
    return 0;
}

编译器退出并声明存在no matching function for call to 'SpecificDerived2::memberFunc(float)'来自gobble函数的错误。仅当派生类或基类具有两个同名但参数不同的重载函数时,才会出现问题。

我正在使用支持 c++11 的 MinGW32 4.8.1。

4

1 回答 1

15

当类模板派生自基类模板时,基类成员在派生类模板定义中不可见。(这是有道理的;在您专门化之前,没有类,因此也没有成员。显式专门化总是可以改变任何给定模板类的含义。)

换句话说,基本模板成员名称是从属名称,并且不会在模板定义查找的第一阶段进行查找。

有三种方法可以解决这个问题。让我们用一个简单的例子来具体说明:

template <typename T> struct Foo
{
    int data;
    using type = const T &; 
    void gobble() const;
    template <int N> void befuddle();
};

template <typename T> struct X : Foo<T> { /* ... */ };

现在在派生类模板定义的上下文中,您可以...

  1. 限定名称:

    Foo<T>::data = 10;
    typename Foo<T>::type x;
    Foo<T>::gobble();
    Foo<T>::template befuddle<10>();
    
  2. 使用this

    this->data = 10;
    this->gobble();
    this->template befuddle<10>();
    

    (这不适用于类型名称。)

  3. 使用using声明:

    using Foo<T>::data;
    using Foo<T>::gobble;
    using type = typename Foo<T>::type;
    
    data = 10;
    gobble();
    

    (这不适用于模板名称。)


更新:编辑后,问题完全不同。模板在这里根本不起作用,因为问题不包含模板,只包含类。发生的事情是一个简单的事实,派生类中的成员函数隐藏了基类中的同名成员函数,因此SpecificDerived2::memberFunc隐藏了基类成员函数。简单的解决方案是使用声明取消隐藏同名的基成员using

class SpecificDerived2 : public TemplateBase2<float>
{
public:
    using TemplateBase2<float>::memberFunc;
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    float memberFunc()
    {
        return 3.14;
    }
};
于 2014-06-11T08:54:29.127 回答