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

template指定されたコードでは、またはを実際に使用する必要はありませんfriend。代わりに継承を使用し、checkMe()メソッドをprotectedand メソッドとして作成しvirtualます。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();
}

派生クラス自体に固有のロジックに加えて、1 つ以上の派生クラスで使用する "共通" ロジックがある場合は、既定の実装が必要になります。その場合は、スコープ解決演算子を使用して、基本クラスのロジックにアクセスします。

    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 に答える