2011-02-10 57 views
11

給定下面的代碼,編譯器顯示一條消息指出error: templates may not be ‘virtual’。有沒有人有如何解決這個錯誤的建議?模板可能不是'虛擬的'

template < class FOO_TYPE> 
class CFoo{ 
    public: 
     ... 
     template < class BAR_TYPE > 
     virtual void doSomething(const CBar<BAR_TYPE> &); // here's the error 
     ... 
     virtual ~CFoo(); 
    protected: 
     MyClass <FOO_TYPE> * m_pClass; 
}; 

template < class FOO_TYPE > 
template < class BAR_TYPE > 
void CFoo<FOO_TYPE>::doSomething(const CBar<BAR_TYPE> & refBar){ 
    ... 
} 
+5

這不是一個錯誤,它是一個功能,你不能聲明一個虛擬的函數模板。你需要探索另一種方法,這取決於你想要做什麼...... – Nim 2011-02-10 19:59:48

+0

事情是函數的參數是一個模板對象,我不能改變它的聲明。 – Javier 2011-02-10 20:02:15

+0

爲什麼你需要爲CBar的每個實例使用不同的函數? – 2011-02-11 08:05:29

回答

16

明白爲什麼這是非法的,最簡單的原因是考慮到虛表。當然,這只是一個普通的實現,而其他的則是允許的。但是C++中的所有功能都可以用vtable實現。

現在,有多少條目在CFoo<int>vtable?有沒有條目doSomething<float>?和doSomething<float*>?和doSomething<float**>?這些模板允許生成無限的函數集。通常這是沒有問題的,因爲你只使用有限的子集,但對於虛函數,這個子集是不知道的,因此vtable需要是無限的。

現在,您可能真的只希望在vtable中有一個條目。

template < class FOO_TYPE, class BAR_TYPE> 
class CFoo{ 
    public: 
     ... 
     virtual void doSomething(const CBar<BAR_TYPE> &); // now OK. 
     ... 
     virtual ~CFoo(); 
    protected: 
     MyClass <FOO_TYPE> * m_pClass; 
}; 

這意味着CFoo<int, float>虛函數表將有一個條目,doSomething(float const&):在這種情況下,你如下寫。

1

那麼,錯誤信息是非常清楚的。 Member function templates can't be virtual。如何解決這個問題取決於你的問題,但最簡單的做法是使成員函數非虛擬並重新考慮你的設計。

+0

謝謝。在我的情況下,我需要這個「refBar」作爲參數,它屬於模板類。 – Javier 2011-02-10 20:12:21

+1

你知道會有多少個不同的模板參數嗎? 3? 8?你可以重載每個這些功能嗎?如果你不知道,編譯器將如何知道它有多少個虛函數? – 2011-02-10 20:35:58

1

如果您確實需要使此方法爲虛擬,請考慮製作CBar<>多態,並傳遞其中未模板化的基本類型。

編輯:這樣的事情:

// non-templated base class 
class BarBase 
{ 
// common methods go here.. 
}; 

template <typename BAR_TYPE> 
class CBar : public BarBase 
{ 
// implement methods from BarBase ... 
}; 

template < class FOO_TYPE> 
class CFoo{ 
    public: 
     ... 
     // now we take the base type, and this method does not need to be a template 
     virtual void doSomething(BarBase const* ptrBar); 
     ... 
     virtual ~CFoo(); 
    protected: 
     MyClass <FOO_TYPE> * m_pClass; 
}; 

template < class FOO_TYPE > 
void CFoo<FOO_TYPE>::doSomething(BarBase const* ptrBar){ 
.. 
} 
1

您可以使用我們在塞班稱作爲「模板設計模式」。下面是示例代碼給你一個想法:

class Base { 
public: 
     virtual int DoSomething() = 0; 
protected: 
     Base(); 
}; 

class IntermediateBase : public Base { 
protected: 
     IntermediateBase(void* aSomeParam, void* aArg) 
     : iSomeParam(aSomeParam) 
     , iArgs(aArg) 
     {} 

     virtual int DoSomething() = 0; 
protected: 
     void* iSomeParam; 
     void* iArgs; 
}; 

template <class TYPE, class INPUT> 
class ConcreteClass : public IntermediateBase { 
     typedef int (TYPE::*MemberFuncPtr)(const INPUT&); 
public: 
     ConcreteClass(TYPE& aCommandType, 
         INPUT& aArgumentsToCommand, 
         MemberFuncPtr aMFP) 
     : IntermediateBase(static_cast<TYPE*>(&aCommandType), 
          static_cast<INPUT*>(&aArgumentsToCommand)) 
     , iMFP(aMFP) 
     {} 

     virtual int DoSomething() // VIRTUAL AND INLINE Note - dont make it 
            // virtual and inline in production if 
            // possible to avoid out-of-line copy 
     { 
      return static_cast<TYPE*>(iSomeParam)->*ConcreteClass::iMFP) 
          (*(static_cast<INPUT*>(iArgs)); 
     } 
private: 
     MemberFuncPtr iMFP; 
};