2010-10-11 45 views
6

Được rồi, tôi đang cố gắng tạo một lớp học nhanh để làm việc như một loại bảng băm. Nếu tôi có thể làm cho nó hoạt động thì tôi có thể làm điều này:toán tử [] = quá tải?

StringHash* hash = new StringHash; 
    hash["test"] = "This is a test"; 
    printf(hash["test"]); 

Và nó sẽ in ra "Đây là một thử nghiệm".

Có vẻ như tôi có 2 vấn đề tại thời điểm này. Thứ nhất tôi đã làm điều này:

const char* operator[](const char* key) { 
    for(int i = 0; i < hashSize; ++i) { 
    if(strcmp(hkeys[i], key) == 0) {return values[i];} 
    } 
    return NULL; 
} 

Nhưng khi tôi cố gắng tìm kiếm một giá trị trình biên dịch phàn nàn rằng

lỗi: không hợp lệ loại 'StringHash * [const char [5]]' cho mảng subscript

Toán tử thứ hai [] = không xuất hiện đúng cú pháp ở đây. Điều duy nhất tôi có thể tìm thấy là & operator [] nhưng tôi không nghĩ rằng sẽ làm việc kể từ khi tôi phải mã thủ tục tra cứu ??? (Không phải cú pháp đó vừa được sử dụng để trả lại một tham chiếu mục mảng?)

Là những gì tôi đang cố gắng làm ở đây thậm chí có thể? Bất kỳ lời khuyên nào được đánh giá cao. :)


Dường như có sự nhầm lẫn về những gì tôi đang cố gắng thực hiện. Tôi sẽ gửi mã của tôi:

http://pastebin.com/5Na1Xvaz


sản phẩm hoàn thành sau khi tất cả sự giúp đỡ:

http://pastebin.com/gx4gnYy8

Trả lời

2

Tôi trước hết sẽ hỏi tại sao bạn đang viết HashMap của riêng mình khi có một số phiên bản có sẵn mặc dù không có phiên bản chuẩn.

Cửa hàng bản đồ băm của bạn có const char * con trỏ hoặc std :: strings không? (Nó có thể lưu trữ const char * con trỏ nếu nó chỉ đơn giản là một bảng tra cứu dữ liệu được lưu trữ ở nơi khác mà sẽ không thay đổi tuổi thọ của nó).

Toán tử [] phải làm gì khi không tìm thấy mục?

Bây giờ hãy để tôi giả định rằng câu trả lời là: - Có, chúng tôi đang lưu trữ const char * con trỏ, và chúng tôi lưu trữ NULL trong ô trống - Khi chúng tôi thực hiện băm [key] = giá trị chúng tôi muốn liên kết khóa giá trị - Nếu chúng ta chỉ làm băm [key] nhưng không viết, nó không chèn

Điều này có thể được thực hiện với một đối tượng ma thuật: khi bạn gán một ký tự const * cho đối tượng này chèn hoặc ghi đè lên băm. Bạn cũng có thể có một chuyển đổi ẩn từ đối tượng thành const char * để đọc.

Điều này khá phức tạp và tốt hơn là nên gắn vào giao diện thường xuyên của bản đồ: toán tử [] luôn chèn và bạn sử dụng một phương pháp khác để tra cứu.

+0

Hmm ... Tôi nghĩ rằng tôi hiểu những gì bạn đang nói. Bạn muốn tôi viết một lớp với toán tử =() và sau đó có xử lý đó thêm mục nhập vào bảng, vâng? Tôi có thể thấy rằng làm việc. Điều mà tôi lo lắng, tôi sẽ không phải lưu trữ một mảng khác trong nội bộ mà sẽ giữ một thể hiện của lớp đó cho mọi ... Ah, không chờ đợi. Tôi chỉ có thể sử dụng những đối tượng như các giá trị nội bộ thay vì const char * và sau đó có họ trả về chuỗi trên tra cứu. Hiểu rồi. :) – Khat

+0

Chụp. Nó sẽ không cho phép tôi làm theo cách này. Nó tiếp tục cố gắng trả lại vật thể ma thuật thay vì dây cstring. – Khat

+1

Bạn có thể xác định chuyển đổi tiềm ẩn giữa loại "ma thuật" và 'const char *'. Tuy nhiên, việc sử dụng 'std :: strings' là một giải pháp mạnh mẽ hơn. –

6

Lỗi này là vì hash là một con trỏ. Thay đổi thành:

StringHash hash; 
+0

Bắt tốt. Cảm ơn bạn. Hiện tại không có lỗi biên dịch. Thử nghiệm ban đầu hoạt động, vì vậy tôi có thể tra cứu các giá trị trong băm bằng khóa của chúng ngay bây giờ. – Khat

3

hash không phải là đối tượng StringHash. Con trỏ của nó là một.

Bạn có thể làm điều này:

(*hash)["test"] = "This is a test";

Hoặc bạn có thể tự hỏi mình tại sao bạn cần một con trỏ để nó ở nơi đầu tiên,

StringHash hash; 
hash["test" = "This is a test"; 

... hoặc thậm chí nếu bạn làm , tại sao bạn sẽ không sử dụng con trỏ thông minh như auto_ptr.

#include <memory> 
std::auto_ptr<StringHash> hash(new StringHash); 
(*hash)["test"] = "This is a test"; 
2

Viết StringHash hash; thay vì new điều. C++ không phải là Java. :-)

3

Các câu trả lời khác liên quan đến câu hỏi đầu tiên của bạn. Đối với lần thứ hai của bạn ...

Nếu bạn trả lại tham chiếu, thì bạn sẽ trả về một giá trị. Bạn luôn có thể gán cho một lvalue.

Có, nó (khá nhiều) thực sự là đơn giản. Tôi khuyên bạn nên đọc kỹ cho dù bạn có cần const ở những nơi khác nhau hay không.

Những gì tôi nhớ đọc là bạn nên cung cấp một const và một phi const quá tải cho operator[], một cái gì đó giống như vậy:

MyType const &operator[](int index) const; // This is the array access version (no assignment allowed), which should work on const objects 
MyType &operator[](int index);  // This is the array access or assignment version, which is necessarily non-const. 

Xem this link để biết thêm thông tin.

2

Lỗi đầu tiên là bạn đã khai báo hàm băm làm con trỏ. Các kiểu con trỏ có thể đã được sử dụng với toán tử chỉ mục. Ví dụ, con trỏ [3] tương đương với * (con trỏ + 3). Bạn không thể thay đổi hành vi đó. Hãy băm chính đối tượng:

StringHash sh; 

Đối với toán tử [] =, không có điều gì như vậy. Toán tử chỉ mục của bạn chỉ cần trả về một tham chiếu để thực hiện công việc gán. Dưới đây là một ví dụ đơn giản về cách này sẽ như thế nào:

class Indexable 
{ 
    std::string arr[3]; 
public: 
    std::string & operator[](int index) { 
     return arr[index]; 
    } 
    std::string const& operator[](int index) const { 
     return arr[index]; 
    } 
}; 
2

Năm vấn đề:

  1. hash là một con trỏ đến một StringHash, bạn phải dereference nó để sử dụng các toán: (*hash)["test"]
  2. Nếu bạn muốn chỉ định cho phần tử, bạn phải trả lại tham chiếu cho loại phần tử

    const char *& operator[] (const char* key);

    // ...

    (*hash)["test"] = "This is a test"; // will compile now

  3. null không phải là một từ khóa trong C++. Sử dụng 0 hoặc NULL.

  4. operator [] phải phân bổ không gian cho một phần tử nếu nó không được tìm thấy. Trả lại NULL không phải là một tùy chọn. Nếu không, cố gắng gán cho kết quả của (*hash)["test"] sẽ làm hỏng chương trình của bạn.
  5. Sử dụng tiêu chuẩn :: bản đồ hoặc tiêu chuẩn :: tr1 :: unordered_map thay vì viết lớp "nhanh" của riêng bạn.

Và chỉ để trở thành một kẻ giật: Bạn biết đó không phải là bảng băm, phải không?

+0

1. Đã sửa lỗi. ty 2. Tôi đang cố gắng quá tải việc phân công phần tử bởi vì tôi muốn giải quyết rval. 3. Nhận thấy rằng ngay sau khi tôi đăng. Đã sửa. ty 4. Xem 2. 5. Không muốn. :) Tại sao nó không phải là bảng băm? – Khat

+0

@ddd: Đây không phải bảng băm vì nó không tính giá trị băm của khóa để lập chỉ mục vào mảng. Xem http://en.wikipedia.org/wiki/Hash_table –

+0

Ah. Tôi hiểu ý bạn là gì. Một bảng thông thường sau đó tôi đoán. – Khat

1

Bạn có thể sử dụng boost::unordered_map<std::string, std::string không? Sau đó, bạn không phải lo lắng về việc thực hiện điều này một mình.

Giả sử đó là một bài tập của một số loại cho chính mình: Bạn có thể đến từ nền khác nhau, nhưng trong C++ theo cách thông thường để khai báo băm của bạn sẽ là:

StringHash hash; 

Ngoài operator[] của bạn có thể làm việc cho bản in nhưng nó sẽ không hoạt động cho bài tập. Thông thường, các phương thức operator[] hoạt động bằng cách trả về tham chiếu không phải là const hoặc một đối tượng proxy mà các giá trị mới có thể được gán, và các phương thức của bạn không được thực hiện. Nếu bạn có thể sử dụng std :: string, bạn có thể viết lại phương thức của mình để trả về tham chiếu không phải const cho vị trí bên trong giá trị băm được đọc hoặc gán.