1

私はC++にかなり慣れていないので、主にPythonを使用しています。作業中のオブジェクトに格納されている値の変数の型を確認しようとしています。Python にはisinstance、次の値が文字列の場合は A を実行し、int の場合は B を実行するなど、特定のコマンドを実行する条件として使用できるコマンドがあったことを覚えています。

C++ で変数のデータ型をすばやく確認する方法はありますか?

例:

Pythonでは、フィールド内の各文字である数学演算を含む配列がありました

[3,"+",2]

配列を読みながら、 isinstance コマンドを使用して文字列から整数を分離します

if isinstance(list[0],int):
        aux1.append(list[0])
        list=list[1:] 
    else:
        if isinstance(lista[0],str):
            aux2.append(list[0
            list=list[1:]

今C ++で同様のことをする必要がありますが、今回は各文字がリンクリストのノードにあり、リンクリストのintと別のリンクリストの文字列を分離する必要があります

4

2 に答える 2

2

あなたが苦労しているように見えるのは、C++ が静的で (比較的) 強く型付けされた言語であるということです。これらの用語のそれぞれが実際に何を意味するかについての議論については、この他の質問を参照してください。

まず第一に、現在試みている方法で実際に物事を行う必要があることを確認する必要があります。Python スタイルのコードを書こうとしないでください。

とは言っても、Python (動的型付け、ダックタイピング、したがって比較的弱い型付け) に似た動作を実現できる基本的に 2 つの異なるアプローチがあります。

  1. C++ の組み込み動的型メカニズムを使用します。したがって、いわゆるポリモーフィック基本クラスを作成する必要があります。これは、少なくとも 1 つの仮想メンバー関数を持つクラスです (デストラクタは、インターフェイスが定義されていない場合でも機能します。ほとんどの場合、厄介なことを避けるために仮想でなければなりません)。問題)。簡単な例:

    struct Value {
      virtual void write_to(std::ostream &) const = 0;
      virtual void read_from(std::istream &) = 0;
      virtual ~Value() {} // Absolutely required!!!
    };
    struct Number : public Value {
      int data;
      void write_to(std::ostream & stream) const {
        stream << "<Number " << data << ">";
      }
      void read_from(std::istream & stream) {
        stream >> data; // Not the same format as write_to, shame on me
      }
      // Implicit destructor is fine
    };
    struct String : public Value {
      std::string data;
      void write_to(std::ostream & stream) const {
        stream << "<String " << data.size() << " " << data << ">";
      }
      void read_from(std::istream & stream) {
        stream >> data; // Not the same format as write_to, shame on me
      }
    };
    

    Valueこれを使用して、たとえば、ユーザーに決定させる実際のタイプの s を格納できます。

    std::vector<std::unique_ptr<Value>> values;
    while (wantsToEnterMoreValues) {
      std::string choice = ask("What type of value do you want to enter?");
      std::unique_ptr<Value> value;
      if (choice == "string") {
        value = std::make_unique<String>();
      } else if (choice == "number") {
        value = std::make_unique<Number>();
      } else {
        // launch apocalypse
      }
      value->read_from(std::cin);
      values.push_back(value);
    }
    

    これは、より多くの型に簡単に拡張できます。C++ の組み込みの動的型付けを使用するには、値のセマンティクスを使用せずに、実際の参照を使用するか、または (上記の例のようにvaluesベクターに所有権を譲渡する必要があるほとんどの場合) を使用して、参照のセマンティクスを完全に使用する必要があることに注意してください。ポインター。

    このdynamic_castアプローチはこれと非常によく似ていますが、実行時の型情報をより明示的に使用し、統一されたインターフェイスを必要としない点が異なります (ただし、コードを維持するために多くの作業が必要になります)。

  2. union言語機能を使用します。これは、C++ 11 でのみ実際に可能になりました。この場合、共用体メンバーは自明に解釈できない可能性があります。

    enum class Type {
      Number, String
    };
    struct Value {
      Type type;
      union {
        std::string string;
        int number;
      };
      Value(std::string const & s) : type(Type::String), string(s) {}
      Value(int n) : type(Type::Number), number(n) {}
      Value(Value const & v) : type(v.type) {
        switch (type) {
          case Type::Number: number = v.number; break;
          case Type::String: new (&string) std::string(v.string); break;
          default: break; // Launch nuclear missiles
        }
      }
      ~Value() {
        switch (type) {
          case Type::String: string.~std::string(); break;
          default: break;
        }
      }
    };
    

    ご覧のとおり、これは非常に多くの作業です。このアプローチでは、値のセマンティクスを使用できますが、Valueより多くの型をサポートするために を簡単に拡張することはできません。さらに、 を使用するためunion、メモリをいくらか浪費することになります。

結論: 自分で動作を実装する必要がありますが、動作を希望どおりに正確に行うことができます。operator=(Value const &)例:暗黙的な型変換を行う代入演算子を実装することもできます。またはのように、 boostの実装を使用することもできます。boost::anyboost::variant

私がこのサイトに書いた2つの回答を参照したいと思います.

また、同じ問題を解決しようとするため、関連するいくつかの C コード: https://stackoverflow.com/a/35443434/1116364

注:この回答のすべてのコードはメモリから直接書かれており、テストされていません。したがって、基本的なテクニックのデモンストレーションとしてのみ機能します。

于 2016-03-07T08:11:55.613 に答える
0

Python とは異なり、C++ は厳密に型指定された言語です。これは、各オブジェクトの型がコンパイル時に認識されることを意味します。

そうは言っても、いくつかの状況で適用できる非常に漠然とした類似物があります。

クラスに少なくとも 1 つの仮想メソッドがあるオブジェクトへのポインターがある場合、 adynamic_castはそれを要求されたクラスへのポインターまたはnullptr. これは、指されている最も派生したオブジェクトがその階層に両方のクラスを明確に含む場合にのみ機能します。

于 2016-03-07T01:35:19.493 に答える