2016-12-02 26 views
5

Tôi gặp khó khăn trong việc hiểu các điều kiện trong đó C++ sẽ sử dụng chuyển đổi ngầm định. Giả sử tôi có một lớp học:Chuyển đổi ngầm C++ trong toán hạng sang toán tử chuẩn

class SomeClass 
{ 
private: 
    int val; 
public: 
    SomeClass(int i) :val{ i } {} 
    operator string() { return to_string(val); } 
}; 

Tại sao khi sử dụng lớp này với toán tử tôi cần truyền tới chuỗi? Tại sao nó không thực hiện chuyển đổi hoàn toàn?

mã:

int main(void) 
{ 
    SomeClass sc = 4; 
    cout << (string)sc << endl; //prints 4, compiles fine 
    cout << sc << endl;//does not compile, no operator "<<" matches these operands 

    string str1 = sc;//compiles fine, performs cast 
    string str2 = "Base String" + sc;//does not compile, no operator "+" matches these operands 
} 

Câu hỏi này là học tập nhiều hơn thực tế như chỉ sử dụng một dàn diễn viên là dễ đọc hơn anyway.

Trả lời

2

Các operator<< overload đó được sử dụng khi bạn viết cout << (string)sc là một hàm template:

template <class CharT, class Traits, class Allocator> 
std::basic_ostream<CharT, Traits>& 
    operator<<(std::basic_ostream<CharT, Traits>& os, 
       const std::basic_string<CharT, Traits, Allocator>& str); 

Điều này là do std::string là chính nó một lớp mẫu, và có thể được khởi tạo với các loại khác hơn char, và vẫn có thể in được nếu các ký tự được ghi vào luồng của cùng một loại ký tự đó. Thực tế, đó chính xác là điều xảy ra với std::wstring, trong đó CharTwchar_t thay vì char. Điều đó tương tự operator<< hoạt động, miễn là bạn sử dụng luồng phù hợp.

Khi bạn viết cout << sc, quá tải cụ thể đó được xem xét. Quá tải đó sau đó bị từ chối bởi vì trình biên dịch không thể suy ra loại nào để sử dụng cho CharT và các loại khác. Nó sẽ chỉ có thể suy ra loại nếu nó đã biết rằng việc chuyển đổi sẽ được thực hiện, nhưng các chuyển đổi không được coi là chỉ được nêu ra, họ sẽ chỉ được kiểm tra trong một giai đoạn hơi muộn hơn.

Nếu có mẫu không quá operator<< quá tải mất std::string, thì nó sẽ hoạt động, sc sẽ được chuyển đổi hoàn toàn.

+0

Vì vậy, để tương thích hơn với các hàm thư viện chuẩn C++ (không có phôi), tôi nên viết các chuyển đổi ngầm đến 'basic_string' và không phải chuỗi? –

+0

@ApoorvaKharche Không, 'string' là một typedef cho một instantiation cụ thể của' basic_string'. Liệu toán tử << 'được viết dưới dạng' basic_string 'hay về' chuỗi' không tạo ra bất kỳ sự khác biệt nào, vì chúng có nghĩa là chính xác điều tương tự. Liệu toán tử << 'có được viết dưới dạng' basic_string 'hoặc' basic_string 'trong đó' T' được suy ra không tạo ra sự khác biệt, và bạn không kiểm soát được điều đó từ lớp của riêng bạn. – hvd

2

std::cout không chấp nhận std::string.
Nó chấp nhận một tempated std::basic_string, các tham số trong đó sẽ được suy luận.
Xem here để biết thêm chi tiết.

Hãy xem xét ví dụ sau:

#include<string> 

struct SomeClass { 
    operator std::string() { return ""; } 
}; 

template <class CharT, class Traits, class Allocator> 
void f(const std::basic_string<CharT, Traits, Allocator> &) {} 

template <class CharT, class Traits, class Allocator> 
void f(std::basic_string<CharT, Traits, Allocator> &) {} 

int main(void) { 
    SomeClass sc{}; 
    f((std::string)sc); 
    //f(sc); 
} 

Nó tương tự như những gì xảy ra trong trường hợp của bạn.
Tất nhiên, f(sc) không biên dịch vì lý do gần như giống nhau.

Vấn đề là để suy ra các tham số mẫu SomeClass phải được chuyển đổi thành std::string. Để có thể chuyển đổi nó thành một std::string, trình biên dịch nên đoán rằng một quá tải hợp lệ tồn tại và cố gắng sử dụng nó. Dù sao, như một chức năng khả thi không tồn tại từ quan điểm của nó, cho các tham số mẫu vẫn còn được suy luận và để suy ra chúng trình biên dịch nên đoán rằng một quá tải cho SomeClass tồn tại sau khi một diễn viên. Nó không thể, bởi vì ... Và vân vân.

Tôi chưa kiểm tra, nhưng tôi sẽ đặt cược rằng điều gì đó tương tự cũng áp dụng cho operator+.

+0

Chính xác là điều gì cho downvote? – skypjack

+0

Vì vậy, để tương thích hơn với các hàm thư viện chuẩn C++ (không có phôi), tôi nên viết các chuyển đổi ngầm tới 'basic_string' và không phải chuỗi? –

+0

Ngay sau câu trả lời này, lịch sử chỉnh sửa đã làm cho nó trông giống như bạn về cơ bản đã sao chép của tôi, nhưng lịch sử chỉnh sửa đã gây hiểu nhầm. Bạn đã đăng một câu trả lời sai, xóa nó khi bạn nhận ra rằng, và cuối cùng sửa chữa nó. Cuối cùng, chúng tôi đơn giản đăng tải về cùng một câu trả lời cùng một lúc. Nếu điều này sẽ xảy ra là lý do ai đó downvoted nó, hãy để cho người đó xin vui lòng hoàn nguyên các downvote. – hvd

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