2014-06-11 102 views
1

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

某些其他类使用派生类进行某些工作并利用其运算符成员函数。只要派生类没有其他重载操作符,即使使用不同的参数数量,一切正常。如果有的话,那么基类操作符就不能使用它作为object(),因为编译器找不到正确的成员函数(抱怨参数计数不匹配)。

指定或不指定基类的默认模板参数。此外,派生类的定义顺序不会更改哪个运算符导致问题(它始终是SpecificDerived类)。

下面我提出简化的问题。

[编辑]实施例进行了简化

基础类定义:

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; 
    } 
}; 
01派生类定义的

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

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

用户

主要功能:

#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功能。只有派生类或基类具有两个具有相同名称但具有不同参数的重载函数时才存在问题。

我正在使用MinGW32 4.8.1和C++ 11支持。

回答

4

当类模板派生自基类模板时,基类成员在派生类模板定义中不可见。 (这是有道理的;直到你专门化,没有班级,所以没有成员,明确的专业化总是可以改变任何给定模板类的含义。)

换句话说,基本模板成员名称是依赖的名称,而不是在模板定义查找的第一阶段查找。

有三种方法可以解决这个问题。让我们把它与具体的一个简单的例子:

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; 
    } 
}; 
+0

然而,在我的例子一切工作得很好,只要有在派生或基类中没有其他重载函数,但是从你说过,看起来即使这样也不行。 – Krzych

+0

@KrzysztofPilch:你可以做一个*小*的例子来说明情况吗? –

+0

我编辑过的例子比较简单。 – Krzych

相关问题