将派生类型传递给基本成员模板函数的优雅方法?

时间:2012-12-10 13:24:13

标签: c++ templates derived-class base-class

我有一个名为'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 ++大师可以帮助我吗?感谢。

3 个答案:

答案 0 :(得分: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-Method。

答案 1 :(得分: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;
    }

答案 2 :(得分:0)

经常有一个常见的伎俩:http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern 这可以帮到你。

相关问题