1

タイプに対して有効な場合に文字列を受け入れる文字列ラッパーをいくつか作成したかったのです。

  • Length有効な文字列:mm、m、ft、in
  • Angle 有効な文字列:deg、rad

私は次のような使用法を想像しました:

Length len = read_from_keyboard(); // or some means of initialization
if( len.is_valid() )   { ...   }

だから私はこれらの実装を書きました。

struct Length
{
  QString m;

  Length() {}

  Length( QString s )   {   if( is_valid_string(s) )  {  m = s; }      }

  QString operator() () {   return m;      }

  bool is_valid()       {   return is_valid_string(m);      }

  static bool is_valid_string( QString s ) { 
    return s == "mm" || s=="m" || s=="ft" || s=="in";
  }
};

struct Angle{
  QString m;

  Angle() {}

  Angle( QString s )    {   if( is_valid_string(s) )  {  m = s; }      }

  QString operator() () {   return m;      }

  bool is_valid()       {   return is_valid_string(m);      }

  static bool is_valid_string( QString s ) { 
    return s == "deg" || s=="rad";
  }
};

is_valid_string()これは、実装における唯一の違いとして、ある種の静的ポリモーフィズムのように思えます。

私はこれらのクラスをいくつか持っているので、共通の機能を把握するために(仮想経由ではなく)静的継承を使用することを考えました。

だから、私は不思議なことに繰り返されるテンプレートパターンを使用することを考えました:

template <class T>
struct ConstrainedText {
  QString m;

  ConstrainedText() {}

  ConstrainedText( QString s ) {   if( T::is_valid_string(s) )   {  m = s;  }    }

  QString operator() ()        {   return m;      }

  bool is_valid()              {   return T::is_valid_string(m);    }

};


struct Angle : public ConstrainedText<Angle> {
   static bool is_valid_string( QString s ) { 
      return s == "deg" || s="rad";
   }  
};


struct Length : public ConstrainedText<Angle> {
   static bool is_valid_string( QString s ) { 
      return s == "mm" || s="m" || s=="ft" || s=="in";
   }  
};

しかし今、私は基本クラス内の暗黙のコンストラクターを失い、それらを書き直さなければなりません!

default constructor同じインターフェース[ 、、implicit constructorおよびis_value()]を持ち、異なる部分(静的)に対して最小限のコードのみを記述するためにこれを実装できる他の方法はありますis_valid_string()か?

プリプロセッサを使用できたはずですが、コードをデバッガに適したものにしたいと考えています。

4

4 に答える 4

1

コンストラクターは継承されないため、。を使用して継承することはできませんusing

C ++ 11では、可​​変個引数テンプレートと完全な転送を使用できます。

template<typename... Args> Derived(Args &&...args):
    Base(std::forward<Args>(args)...) {}
于 2012-09-10T16:40:19.360 に答える
1

他の人が指摘しているように、コンストラクターは継承されないため、コンストラクターを再定義する必要があります。ただし、このようなことを行うことはできます。ideone.comでコードを記述してください

#include <string>
#include <stdexcept>
#include <iostream>

template <class T>        
class ConstrainedText {        
  std::string m;                 

protected:
  ConstrainedText() {}
  ~ConstrainedText() {}
public: 
  bool is_valid() {        
    return T::is_valid_string(m);        
  }        

  static T Create(std::string const & s)
  {
      if (T::is_valid_string(s)) {
          T t;
          static_cast<ConstrainedText<T>&>(t).m = s;
          return t;
      }

      throw std::runtime_error("invalid input!");
  }
};        

struct Angle : public ConstrainedText<Angle> {        
   static bool is_valid_string( std::string s ) {         
      return s == "deg" || s=="rad";        
   }          
};        


struct Length : public ConstrainedText<Length> {        
   static bool is_valid_string( std::string s ) {         
      return s == "mm" || s == "m" || s == "ft" || s == "in";        
   }          
};        

int main()
{
   auto a = Angle::Create("deg");
   auto l = Length::Create("mm");

   try {
       Angle::Create("bimbo");
   } catch (std::runtime_error & pEx) {
       std::cout << "exception as expected" << std::endl;
   }

   try {
       Length::Create("bimbo");
   } catch (std::runtime_error & pEx) {
       std::cout << "exception as expected" << std::endl;
   }
}
于 2012-09-10T17:27:03.993 に答える
0

コンストラクターはC++で継承されることはないため(コンストラクターが定義されていない場合のデフォルトを除く)、自分でコンストラクターを再度実装するか、コンパイラーをコンストラクターと一致させるために(C ++ 11可変個引数テンプレートの有無にかかわらず)テンプレートを作成する必要があります。ただし、そうすると、無意味なテンプレートコンストラクターが(場合によっては)紛らわしい抽象化レイヤーを追加するため、ドキュメントやコンパイラーのエラーの解釈が難しくなることに注意してください。

プリプロセッサ演算子もこれを回避できますが、コンストラクターが非常に単純で、すべての継承者間で簡単に複製できる場合にのみ回避します。

したがって、一般に、継承されたデフォルトコンストラクターと暗黙のコンストラクターを自動的に生成できるかどうかの答えはノーです。しかし、上で概説した2つのアプローチは、やや厄介ですが自動的な方法でそれを行います。

于 2012-09-10T16:54:55.510 に答える
0

ポリシーを使用したところ、その日が節約されました。これで、コンストラクターを書き直す必要はなく、を実装するだけで済みますis_valid_string()。現在はC++98にも準拠しています。

template <class Policy>
struct ConstrainedText {
  QString m;

  ConstrainedText() {}

  ConstrainedText( QString s ) {   if( Policy::is_valid_string(s) )   {  m = s;  }    }

  QString operator() ()        {   return m;      }

  bool is_valid()              {   return Policy::is_valid_string(m);    }

};


struct Angle_policy {
   static bool is_valid_string( QString s ) { 
      return s == "deg" || s="rad";
   }  
};

struct Length_policy {
   static bool is_valid_string( QString s ) { 
      return s == "mm" || s="m" || s=="ft" || s=="in";
   }  
};

typedef ConstrainedText<Length_policy> Length;
typedef ConstrainedText<Angle_policy>  Angle;

よろしくお願いします

于 2012-09-11T08:37:44.003 に答える