5

Tôi xác định nhiều quá tải của các nhà điều hành phân như sau:Boolean và String quá tải của toán tử gán (C++)

foo.h

class Foo 
{ 
private: 
    bool my_bool; 
    int my_int; 
    std::string my_string; 
public: 
    Foo& operator= (bool value); 
    Foo& operator= (int value); 
    Foo& operator= (const std::string& value); 
}; 

Foo.cpp

// Assignment Operators. 
Foo& Foo::operator= (bool value) {my_bool = value; return *this;} 
Foo& Foo::operator= (int value) {my_int = value; return *this;} 
Foo& Foo::operator= (const std::string& value) {my_string = value; return *this;} 

Và đây là main.cpp của tôi (xem nhận xét được đánh dấu SURPRISE):

Foo boolFoo; 
Foo intFoo; 
Foo stringFoo; 

// Reassign values via appropriate assignment operator. 
boolFoo = true;    // works...assigned as bool 
intFoo = 42;     // works...assigned as int 
stringFoo = "i_am_a_string"; // SURPRISE...assigned as bool, not string 

std::string s = "i_am_a_string"; 
stringFoo = s;     // works...assigned as string 

// works...but awkward 
stringFoo = static_cast<std::string>("i_am_a_string"); 

Câu hỏi: Ai đó có thể cho tôi biết lý do tại sao một chuỗi ký tự không được hiển thị đang được đánh giá trong ngữ cảnh boolean?

+0

@Mooing Duck: Tại sao xóa các nhà thầu? Tôi đã thêm chúng để cố tình chỉ ra rằng một biến có thể được *** khởi tạo thông qua một hàm tạo, và sau đó *** gán lại *** thông qua một toán tử gán. (Như tôi đã thấy trong các bài viết SO khác, đôi khi bạn cần *** cả ***.) – DavidRR

+2

Tôi đã cắt mã vì [Câu hỏi hay có ví dụ ngắn gọn có thể biên dịch được] (http://sscce.org/) và [mã của bạn có thể ngắn hơn và đơn giản hơn và vẫn tái tạo vấn đề] (http://ideone.com/W2nemc). Lần đầu tiên tôi không đọc hầu hết câu hỏi của bạn, bởi vì nó có quá nhiều mã trong đó, và tôi đoán (chính xác) rằng hầu hết nó không liên quan đến câu hỏi của bạn. –

+0

@Mooing Duck: Vâng, tôi rất đồng ý về nguyên tắc và đã xem xét điều này khi thêm các nhà thầu vào ví dụ của tôi. Nhưng tôi sẽ trì hoãn phán đoán của bạn ở đây. Tuy nhiên, hy vọng của tôi là bất cứ ai đi qua bình luận của tôi sẽ biết để xem xét các contructors liên quan là tốt. – DavidRR

Trả lời

9

C++ chuẩn định nghĩa quy tắc giải quyết tình trạng quá tải trong chương 13.3, có bạn tìm thấy:

13.3.3.2 Ranking trình tự chuyển đổi ngầm [over.ics.rank]

Khi so sánh các dạng chuyển đổi tiềm ẩn cơ bản (như được định nghĩa trong 13.3.3.1)

- chuỗi chuyển đổi chuẩn (13.3.3.1.1) là chuỗi chuyển đổi tốt hơn so với trình tự do người dùng xác định chuỗi chuyển đổi hoặc chuỗi chuyển đổi dấu ba chấm và

- chuỗi chuyển đổi do người dùng xác định (13.3.3.1.2) là chuỗi chuyển đổi tốt hơn chuỗi chuyển đổi dấu ba chấm (13.3.3.1.3).

Điều này có nghĩa là trình biên dịch sẽ thích chuỗi chuyển đổi chuẩn từ chuỗi ký tự thành bool hoặc int nếu có. Bây giờ, chuyển đổi chuẩn nào có liên quan? Trong trường hợp của bạn, hai là liên quan:

4,2 Mảng-to-con trỏ chuyển đổi [conv.array]

Một vế trái hoặc rvalue kiểu “mảng của NT” hoặc “mảng không biết ràng buộc của T ”có thể được chuyển đổi thành một giá trị của loại" con trỏ đến T ". Kết quả là một con trỏ đến phần tử đầu tiên của mảng.

Chuyển đổi này chuyển chuỗi ký tự bằng loại const char[N] thành số const char*. Điều thứ hai là:

4,12 chuyển đổi Boolean [conv.bool]

Một prvalue của số học, liệt kê unscoped, con trỏ, hoặc con trỏ đến loại thành viên có thể được chuyển đổi sang một prvalue của nhập bool. Giá trị bằng không, giá trị con trỏ null hoặc giá trị con trỏ thành viên null được chuyển đổi thành false; bất kỳ giá trị nào khác được chuyển đổi thành true. Giá trị của loại std::nullptr_t có thể được chuyển đổi thành giá trị loại bool; giá trị kết quả là false.

Đó là lý do tại sao con trỏ được chuyển đổi thành bool. Vì chuỗi chuyển đổi chuẩn tồn tại, nên chuyển đổi do người dùng xác định thành std::string không được sử dụng.

Để giải quyết sự cố của bạn, tôi khuyên bạn nên thêm một phiên bản quá tải khác mất const char* và chuyển tiếp cuộc gọi đến quá tải const std::string&.

+0

Cảm ơn, Daniel! Các bài học khác cho tôi ở đây là một chuỗi các bản đồ chữ cái để 'char *' (thông qua 'char [N]'), * không * 'std :: string'. – DavidRR

+1

@DavidRR: chúng phải là 'const char *' và 'const char [N]', nhưng có. –

+0

+1 để trích dẫn tiêu chuẩn và giải thích. –

3

Daniel nói đúng.

Câu trả lời ngắn gọn là std::string không phải là loại được tích hợp sẵn và, do đó, không nhận được bất kỳ điều trị ưu đãi kỳ diệu nào. Và thật không may, loại chuỗi ký tự như "hi world"không phảistd::string, nhưng loại con trỏ dễ dàng chuyển đổi thành kiểu dựng sẵn bool so với loại "do người dùng xác định" & dagger; loại std::string.

Về cơ bản, câu trả lời là: chào mừng bạn đến với C++.

& dagger; Vâng, tôi biết, từ thư viện tiêu chuẩn và, không, không quan trọng.

+0

Tôi nghĩ rằng một người nào đó bị bỏ rơi vì câu cuối cùng xuất hiện như một chút lén lút. –

+2

@Mooing: Nếu nó lén lút, sau đó nó lén lút ở C++. Nếu ai đó đang dùng cá nhân _that_ thì tốt thôi, họ vượt ra ngoài sự giúp đỡ của tôi. –

+0

Là người đăng câu hỏi, tôi hoàn toàn không bị xúc phạm bởi "chào mừng bạn đến với C++". Tôi đang tìm C++ là khá khác nhau từ Java và C#. Với C++, chắc chắn có vẻ như có nhiều cơ hội hơn để gặp rắc rối ... – DavidRR

Các vấn đề liên quan