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;
}

commecnt“按名称搜索”下方的代码负责此结果。我想要做的是创建一个添加到 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 回答