2012-12-10 45 views
0

我有一個名爲類的ValueChecker'將派生類型傳遞給基礎成員模板函數的優雅方式?

其具有以下成員函數:

template<typename T> 
bool ValueChecker::checkMe(std::ostringstream &oss, T &me) { 
    std::cout << "Default checkMe() for " << typeid(me).name() << std::endl; 
    return true; 
} 

類ValueChecker意圖做派生類的值有一些簡單的檢查。 checkMe()最終會得到專門爲不同的派生類:

class Airplane : public ValueChecker { 
    friend class ValueChecker; 
    [...] 
} 


template<> 
bool ValueChecker::checkMe<Airplane>(std::ostringstream &oss, Airplane &me) { 
    ...  
    /* Actually, this code is generated from a simple file which translates 
    * a simple language into C++ code. So that a non-developer can write 
    * the simple checks. 
    * 
    * ValueChecker itself has utility functions that may be called in the 
    * template specialization which are shared across all types. 
    */ 

} 

這工作,但只是一個小問題,checkMe的聲明,當你在調用:

int main() { 
    Airplane plane; 
    std::ostringstream oss; 

    if(plane.checkMe(oss, plane)) { 
    cout << "Values are bogus! " << oss.str() << endl; 

    return 0; 
} 

我調用plane.checkMe(oss,plane)。但是,我可以通過另一架飛機,而不是檢查飛機。此外,調用是多餘的?意思是,理論上,編譯器應該根據平面的類型知道調用哪個模板函數。不應該有必要將它作爲一個參數來傳遞?無論如何,最好不要消除最後一個論點。所以這樣的電話會很好:

if(plane.checkMe(oss)) { ... } // Calls the right template specialization. 

我只是不能得到它的工作。 C++專家在這裏能幫助我嗎?謝謝。

+0

我們不能在typeid中傳遞這個指針嗎? –

+0

你評價過CRTP嗎?(http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) – Chubsdad

+0

這首先看起來很奇怪。爲什麼'Airplane'派生自'ValueChecker'?爲什麼'checkMe()'當(從你的問題來判斷)它應該只檢查'this'的時候帶一個'T'類型的參數? – Angew

回答

3

您可能希望將其實現爲純虛擬方法。

class ValueChecker 
{ 
public: 
    virtual bool checkMe(std::ostringstream& oss) = 0; 
}; 

class Airplane : public ValueChecker 
{ 
public: 
    virtual bool checkMe(std::ostringstream& oss); 
}; 

這樣,你可以叫plane.checkMe(oss)和飛機的checkMe-方法將被調用。

3

對於您給定的代碼,您並不需要使用templatefriend。而是使用繼承,並使checkMe()方法爲protectedvirtual方法。然後覆蓋派生類中的checkMe()方法。如果你不需要默認的實現,那麼你可以使它成爲純虛擬的。這裏有一個基於你的例子的快速代碼片段。 (注意使用this指針。)

class ValueChecker { 
protected: 
    virtual bool checkMe() { 
     std::cout << "Default checkMe() for " << typeid(this).name() << std::endl; 
     return true; 
    } 
}; 

class Airplane : public ValueChecker { 
public:  
    virtual bool checkMe() { 
     std::cout << "Airplane checkMe() for " << typeid(this).name() << std::endl; 
     return true; 
    } 
}; 

int main() { 
    Airplane plane; 
    plane.checkMe(); 
} 

您將需要一個默認的實現時,有你想在一個或多個派生類使用一些「常見」的邏輯,除了邏輯具體派生類本身。在這種情況下,使用範圍解析運算符來訪問基類的邏輯。

bool Airplane::checkMe() { 
     std::cout << "Airplane checkMe() for " << typeid(this).name() << std::endl; 

     // use the "common" logic from the base class (if required) 
     ValueChecker::checkMe(); 

     return true; 
    } 
+0

@Bitdiot如果您的查詢已解決,您可以請upvote答案並接受答案? (我更喜歡我的:)) –

相關問題