2012-04-23 66 views
10

EDIT: Theo nhận xét của Mike Seymour, tôi đã thay thế operator std::string() const; bằng operator char *() const; và thay đổi việc triển khai tương ứng. Điều này cho phép đúc ngầm, nhưng, vì lý do nào đó, toán tử int dài chưa ký được ưu tiên hơn toán tử char *, điều này không cảm thấy đúng ... Ngoài ra, tôi không muốn để lộ những thứ C khó chịu như char * bên ngoài lớp, khi tôi có std :: string. Tôi có một linh cảm mà lớp CustomizedInt của tôi cần phải kế thừa từ một số thứ để hỗ trợ tính năng mà tôi mong muốn. Ai có thể vui lòng xây dựng bình luận của Mike về std::basic_string? Tôi không chắc tôi hiểu nó đúng cách.C++ Nhà điều hành chuyển đổi ngầm định Ưu tiên


Tôi có đoạn mã này:

#include <string> 
#include <sstream> 
#include <iostream> 

class CustomizedInt 
{ 
private: 
    int data; 
public: 
    CustomizedInt() : data(123) 
    { 
    } 
    operator unsigned long int() const; 
    operator std::string() const; 
}; 

CustomizedInt::operator unsigned long int() const 
{ 
    std::cout << "Called operator unsigned long int; "; 
    unsigned long int output; 
    output = (unsigned long int)data; 
    return output; 
} 

CustomizedInt::operator std::string() const 
{ 
    std::cout << "Called operator std::string; "; 
    std::stringstream ss; 
    ss << this->data; 
    return ss.str(); 
} 

int main() 
{ 
    CustomizedInt x; 
    std::cout << x << std::endl; 
    return 0; 
} 

nào in "nhà điều hành gọi là unsigned long int; 123". Câu hỏi của tôi là:

  1. Sau khi tôi xóa toán tử unsigned long int, tại sao tôi cần truyền x thành std :: string một cách rõ ràng? Tại sao nó không gọi toán tử ngầm ẩn (std :: string) trực tiếp?
  2. Có bất kỳ tài liệu nào giải thích những phôi ngầm tiềm ẩn nào được phép không và đó là thứ tự ưu tiên của chúng? Có vẻ như nếu tôi thêm toán tử unsigned int vào lớp này cùng với toán tử unsigned long int, tôi nhận được lỗi biên dịch về sự mơ hồ cho nhà điều hành < < ...
  3. Ngoài ra, tôi biết rằng việc định nghĩa toán tử như vậy có thể thực hành kém, nhưng tôi không chắc rằng tôi hoàn toàn hiểu được những cảnh báo liên quan. Ai đó có thể phác thảo chúng? Nó sẽ được thực hành tốt hơn để chỉ xác định phương pháp công khai ToUnsignedLongInt và ToString?
+0

Điều này liên quan: [Sự cố phân giải quá tải khi truyền trực tuyến đối tượng qua chuyển đổi ẩn thành chuỗi] (http://stackoverflow.com/questions/6677072/overload-resolution-failure-when-streaming-object-via-implicit-conversion -to-str) –

+0

@Als: Hãy lấy nó từ từ ... Tôi chưa chuẩn bị để đi sâu vào các mẫu chưa :) –

Trả lời

8

Sau khi tôi xóa toán tử unsigned long int, tại sao tôi cần truyền x thành std :: string một cách rõ ràng? Tại sao nó không gọi toán tử ngầm ẩn (std :: string) trực tiếp?

Các phiên bản của << cho chuỗi là một mẫu, parametrised bởi các thông số của std::basic_string mẫu (std::string bản thân trở thành một chuyên môn hóa của mẫu đó). Nó chỉ có thể được lựa chọn bằng cách tra cứu phụ thuộc vào đối số, và nó chỉ hoạt động nếu đối số thực sự là một chuyên môn của std::basic_string, không phải là một cái gì đó chuyển đổi thành điều đó.

Có bất kỳ tài liệu nào giải thích những phôi tiềm ẩn nào được phép không và đó là thứ tự ưu tiên của chúng?

Quy tắc khá phức tạp và bạn cần phải đọc tiêu chuẩn C++ cho toàn bộ câu chuyện. Quy tắc đơn giản là chuyển đổi tiềm ẩn không được chứa nhiều chuyển đổi do người dùng xác định và (như bạn đã phát hiện ra) kết quả của chuyển đổi tiềm ẩn không thể được sử dụng để chọn chuyên môn mẫu theo tra cứu phụ thuộc vào đối số.

Tôi không chắc mình hoàn toàn hiểu được các cảnh báo liên quan. Ai đó có thể phác thảo chúng?

Tôi cũng không hiểu hết chúng; tương tác giữa chuyển đổi tiềm ẩn, tra cứu tên và chuyên môn về mẫu (và có lẽ các yếu tố khác mà tôi không thể nghĩ ra ngay bây giờ) khá phức tạp và hầu hết mọi người không có khuynh hướng để tìm hiểu tất cả.Có khá nhiều trường hợp chuyển đổi ngầm sẽ không xảy ra và những trường hợp khác có thể xảy ra khi bạn không mong đợi; cá nhân, tôi thấy dễ dàng hơn là tránh hầu hết các chuyển đổi tiềm ẩn.

Thực hành tốt hơn để chỉ xác định phương thức công khai ToUnsignedLongInt và ToString?

Đó có thể là một ý tưởng hay, để tránh các chuyển đổi không mong muốn. Bạn có thể khắc phục vấn đề của bạn bằng cách để lại họ và sử dụng chúng một cách rõ ràng khi cần thiết:

std::cout << std::string(x) << std::endl; 

Trong C++ 11, bạn có thể khai báo explicit, vì vậy mà họ chỉ có thể được sử dụng theo cách này. Theo tôi, đó sẽ là lựa chọn tốt nhất nếu bạn có thể; nếu không, tôi sẽ sử dụng các hàm chuyển đổi rõ ràng như bạn đề xuất.

Nhân tiện, loại trả lại là main() phải là int, không phải void.

+0

Mike: Cảm ơn bạn đã dành thời gian để cung cấp một nhận xét chi tiết như vậy. Nó làm sáng tỏ mọi thứ một chút. Ngoài ra, cảm ơn vì đã phát hiện ra vấn đề nhỏ với "void main". Tôi nên nhớ sử dụng phiên bản chính xác, không có vấn đề gì :) –

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