2012-12-10 15 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答案并接受答案? (我更喜欢我的:)) –

相关问题