2015-07-28 32 views
1

我想重載下標運算符-i知道它作爲元素訪問運算符采取char *或std ::字符串。重載矢量下標運算符采取一個字符*或字符串

我有一個結構

struct foo 
{ 
    int Age; 
    const char *Name; 
}; 

和將要舉辦這個結構的多個實例,一個std ::向量。

std::vector<foo>bar; 

我的目標是能夠通過調用他們的名字來訪問每個富酒吧。

std::cout<<"Simon's age is: "<<bar["simon"]; 

我剛剛被谷歌搜索了很久,而試圖找到一個例子或東西走下車,沒有運氣。

我認爲這會工作

foo operator[](char *Name) 
{ 
    for(int i=0;i<bar.size();i++) 
    { 
     if(bar[i].Name == Name){return bar[i];} 
    } 
} 

但是顯然我做錯了

我知道這可能是與一個std ::地圖做,但我寧願使用一個std ::矢量,謝謝。

但是,如果您選擇提供幫助,我將非常感謝您的幫助。謝謝 。

+1

*「但顯然我做錯了什麼」* - 錯誤是什麼?沒有信息,我們無法真正幫助你 – hlt

+6

你有沒有任何理由不使用std :: map,它只提供你正在尋找的功能? – user463035818

+0

不,你不能像這樣重載一個下標操作符。你可能想創建一個'std :: map'。 –

回答

3

做你想要的東西需要從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 
    } 
}; 
+0

如果你從'std :: vector'繼承,你仍然不能重載它的方法。你只能重載*你的類的方法。不建議繼承標準容器。 –

+0

@ user3063807如果你不習慣從一個模板類繼承,一個很大的驚喜將是你不能簡單地使用該類的公有或受保護的成員作爲'member',並讓編譯器推斷出這個意思是'this- > member'(如果基類不是模板的話,你可以這樣做)。一個例子是我使用上面的size()。這個問題有幾種解決方法。最好的解決方法就是我在上面的代碼中用'using'顯示的內容。 – JSF

+0

@ n.m。據我所知,從標準容器繼承是「不推薦」的一些非常蹩腳的原因,在你想從一個標準容器繼承的情況下幾乎從來沒有問題。例如,如果您從任何缺乏虛擬析構函數的類繼承,則不應該使用基類指針來刪除該派生類對象。但是有一個派生類是非常普遍的,因爲它從來沒有任何理由支持基類指針的刪除。 – JSF

1
bar[i].Name == Name 

大概意思是

strcmp(bar[i].Name, Name) == 0 

但是,你會使用std::string總比管理的char指針會更好。

而不是繼承形式向量,創建一個向量作爲成員的類,並有該類的operator[]

0

首先是有一些問題,你的測試:

1)您使用的字符串類型爲const char *,用==比較,你要比較兩個指針可能會失敗,不是他們的內容。你需要使用strcmp或更好地使用std :: string(C++方式)

2)如果你的索引操作符找不到你要查找的值,該怎麼辦?

我不認爲這是這樣做的正確方法,但如果你真的想使用矢量可以繼承自己的類並定義它使用爲const char new運算符*爲指標參數:

#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容器繼承(它們沒有虛擬析構函數),但如果不向繼承類添加任何數據屬性,則應該沒問題。

但我建議你考慮使用std :: map作爲容器,std :: string作爲索引/名稱屬性類型。搜索向量具有線性複雜性,但std :: map具有對數複雜性。或者你可以考慮使用散列表。