7

したがって、ベクター内のオブジェクトの文字列を「検索」できるようにする次のコードがあります。

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <string>

struct migObj
{
    migObj(const std::string& a_name, const std::string& a_location) : name(a_name),             location(a_location) {}
    std::string name;
    std::string location;
};

int main()
{
    typedef std::vector<migObj> migVec;
    migVec v;
    v.push_back(migObj("fred", "belfast"));
    v.push_back(migObj("ivor", "london"));

    // Search by name.
    const std::string name_to_find = "ivor";
    auto i = std::find_if(v.begin(), v.end(), [&](const migObj& obj) { return name_to_find == obj.name;});
    if (i != v.end())
    {
        std::cout << i->name << ", " << i->location << "\n";
    }

    return 0;
}

「名前で検索」というコマンドの下のコードが、この結果に関与しています。私がやりたいことは、std::vector または typedef migVec に追加されるメソッドを作成することです。

v.myNewSearchFunction("ivor");
4

2 に答える 2

9

それはできません。C++ には、C# にあるような拡張メソッドがありません。

ベクトルからクラスを派生させることもできますが、その場合、すべてのクライアント コードを変更する必要があります。その上、Roddy が指摘しているように、std::vector には仮想デストラクタがないため、それを派生させることは一般的に悪い考えです。

IMO、単純な関数を書く方がはるかに良い選択です。追加の利点は、他のほとんどのコンテナー (例: std::list) でも機能し、通常は無料の関数でもある STL のほとんどのアルゴリズムとの互換性が高いことです。

したがって、代わりに次のようになります。

myNewSearchFunction(v, "ivor"); // instead of v.myNewSearchFunction("ivor");

内部的には、この関数はstd::find_if(v.begin(), v.end(), ....

std::begin(v), std::end(v)ところで、よりも使用する方が良いことに注意してくださいv.begin(), v.end()。これにより、配列などで同じコードを実行できます。

C++ では、物事をクラスに入れることが常に最良の選択であるとは限りません

于 2013-05-29T11:34:12.137 に答える
4

それは可能ではありません。少なくとも推奨できる方法ではありません。

少し詳しく説明すると、C++ クラスを「拡張」して、主要な定義よりも多くのメソッドを持つことはできません。つまり、クラスを再定義したり、その定義を「再度開いて」機能を追加したりすることはできません。

あなたがすべきこと: ベクトルを最初のパラメーターとしてとるフリー関数を書きます。それはメソッドを書くのと同じくらい良いことであり、警告はありません。生成されたアセンブラーは、新しいメソッドと同じになる可能性があります。

migVec::const_iterator findByName(migvec const& mv, std::string const& name) {
  return std::find_if(std::cbegin(mv), std::cend(mv), [&](const migObj& obj) { 
    return name == obj.name;
  });
}

//...
auto pos = findByName(v, "ivor");

理論的にはできるがすべきではないこと:

  • から派生しstd::vectorます。これをしないでください。から派生するように設計されていないため、多くの問題が発生する可能性があります。
  • 特化するstd::vector<migObj>。標準ライブラリ テンプレートの完全な特殊化を提供することが許可されています。ただし、特殊化されたベクトルの完全な定義を提供する必要があります。つまり、すべての標準メソッドと、必要な新しいメソッドを意味します。std::vectorこれを実現するには、ライブラリ ヘッダーから の定義を実質的にコピーするか(これは移植性がありません)、独自の定義をロールする必要がありますが、これは面倒な作業です。そこに行かないでください。
于 2013-05-29T11:49:05.507 に答える