2014-06-11 54 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

相關問題