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++ 大师能帮我吗?谢谢。

4

3 回答 3

4

对于您给定的代码,您实际上并不需要使用templateor friend。而是使用继承,并将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;
    }
于 2012-12-10T13:41:46.160 回答
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 就会被调用。

于 2012-12-10T13:32:57.110 回答
0

有一个经常使用的常见技巧:http ://en.wikipedia.org/wiki/Curiously_recurring_template_pattern 可以为您解决问题。

于 2012-12-10T13:48:14.910 回答