重载向量下标运算符取一个 char * 或 string
Overload vector subscript operator to take a char * or string
我正在尝试重载下标运算符 - 我知道它是元素访问运算符 - 以获取 char * 或 std::string。
我有一个结构
struct foo
{
int Age;
const char *Name;
};
和一个 std::vector 将持有该结构的多个实例。
std::vector<foo>bar;
我的目标是能够通过调用名称来访问 bar 中的每个 foo。
std::cout<<"Simon's age is: "<<bar["simon"];
我一直在搜索 google 很长时间,试图找到一个示例或其他可以解决的问题,但没有成功。
我认为这会起作用
foo operator[](char *Name)
{
for(int i=0;i<bar.size();i++)
{
if(bar[i].Name == Name){return bar[i];}
}
}
然而显然我做错了什么
我知道这可以用 std::map 来完成,但我宁愿使用 std::vector,谢谢。
无论您选择提供何种帮助,我都将不胜感激。谢谢。
bar[i].Name == Name
可能是
strcmp(bar[i].Name, Name) == 0
但是,使用 std::string
s 比管理普通字符指针更好。
而不是从向量中继承,而是创建一个 class 并将向量作为成员,并将你的 operator[]
放在 class 上。
做你想做的事需要从 std::vector 继承。否则你不能重载它的方法。
类似于以下内容(未经测试)。
struct fooVector : public std::vector<foo> {
typedef std::vector<foo> super;
using super::size;
...
foo& operator[](char const* Name) {
super& self=*this;
for(int i=0;i<size();i++)
{
if( ! strcmp( self[i].Name, Name) ){return self[i];}
}
// Need to do something reasonable if not found
}
};
首先你的测试有一些问题:
1) 您正在使用 const char* 作为字符串类型,与 == 进行比较可能会失败,因为您比较的是两个指针而不是它们的内容。您需要使用 strcmp 或更好地使用 std::string(c++ 方式)
2) 如果您的索引运算符找不到您要查找的值怎么办?
我认为这不是一个正确的方法,但如果你真的想使用向量,你可以继承你自己的 class 并定义使用 const char* 作为索引参数的新运算符:
#include <vector>
#include <iostream>
#include <string.h>
struct foo {
int age;
const char *name;
};
class MyVector : public std::vector<foo> {
public:
const foo* operator[](const char* name) const {
for (auto it=cbegin(); it != cend(); ++it) {
if (strcmp(it->name, name) == 0) {
return &(*it);
}
}
return nullptr;
}
};
int main(int argc, char *argv[]) {
foo foo1 = { 10, "abc" };
foo foo2 = { 20, "test" };
MyVector v;
v.push_back(foo1);
v.push_back(foo2);
std::cout << "test: " << v["test"]->age << std::endl;
}
虽然通常不建议从 stl 容器继承(它们没有虚拟析构函数),但如果您不向继承的对象添加任何数据属性class,您应该没问题。
但我建议您考虑使用 std::map 作为容器,使用 std::string 作为索引/名称属性类型。搜索向量具有线性复杂度,但 std::map 具有对数复杂度。或者你可以考虑使用哈希表。
我正在尝试重载下标运算符 - 我知道它是元素访问运算符 - 以获取 char * 或 std::string。
我有一个结构
struct foo
{
int Age;
const char *Name;
};
和一个 std::vector 将持有该结构的多个实例。
std::vector<foo>bar;
我的目标是能够通过调用名称来访问 bar 中的每个 foo。
std::cout<<"Simon's age is: "<<bar["simon"];
我一直在搜索 google 很长时间,试图找到一个示例或其他可以解决的问题,但没有成功。
我认为这会起作用
foo operator[](char *Name)
{
for(int i=0;i<bar.size();i++)
{
if(bar[i].Name == Name){return bar[i];}
}
}
然而显然我做错了什么
我知道这可以用 std::map 来完成,但我宁愿使用 std::vector,谢谢。
无论您选择提供何种帮助,我都将不胜感激。谢谢。
bar[i].Name == Name
可能是
strcmp(bar[i].Name, Name) == 0
但是,使用 std::string
s 比管理普通字符指针更好。
而不是从向量中继承,而是创建一个 class 并将向量作为成员,并将你的 operator[]
放在 class 上。
做你想做的事需要从 std::vector 继承。否则你不能重载它的方法。
类似于以下内容(未经测试)。
struct fooVector : public std::vector<foo> {
typedef std::vector<foo> super;
using super::size;
...
foo& operator[](char const* Name) {
super& self=*this;
for(int i=0;i<size();i++)
{
if( ! strcmp( self[i].Name, Name) ){return self[i];}
}
// Need to do something reasonable if not found
}
};
首先你的测试有一些问题:
1) 您正在使用 const char* 作为字符串类型,与 == 进行比较可能会失败,因为您比较的是两个指针而不是它们的内容。您需要使用 strcmp 或更好地使用 std::string(c++ 方式)
2) 如果您的索引运算符找不到您要查找的值怎么办?
我认为这不是一个正确的方法,但如果你真的想使用向量,你可以继承你自己的 class 并定义使用 const char* 作为索引参数的新运算符:
#include <vector>
#include <iostream>
#include <string.h>
struct foo {
int age;
const char *name;
};
class MyVector : public std::vector<foo> {
public:
const foo* operator[](const char* name) const {
for (auto it=cbegin(); it != cend(); ++it) {
if (strcmp(it->name, name) == 0) {
return &(*it);
}
}
return nullptr;
}
};
int main(int argc, char *argv[]) {
foo foo1 = { 10, "abc" };
foo foo2 = { 20, "test" };
MyVector v;
v.push_back(foo1);
v.push_back(foo2);
std::cout << "test: " << v["test"]->age << std::endl;
}
虽然通常不建议从 stl 容器继承(它们没有虚拟析构函数),但如果您不向继承的对象添加任何数据属性class,您应该没问题。
但我建议您考虑使用 std::map 作为容器,使用 std::string 作为索引/名称属性类型。搜索向量具有线性复杂度,但 std::map 具有对数复杂度。或者你可以考虑使用哈希表。