2014-10-16 27 views
8

Tại sao C++ đúc chuỗi ký tự tôi chuyển vào dưới dạng bool thay vì chuỗi?Quá tải Bool/String Sự mơ hồ

#include <iostream> 

using namespace std; 

class A 
{ 
    public: 
     A(string v) 
     { 
      cout << v; 
     } 

     A(bool v) 
     { 
      cout << v; 
     } 
}; 

int main() 
{ 
    A("hello"); 
    return 0; 
} 

Output: 1

Có phải vì trình biên dịch là không đủ thông minh để thực hiện chuyển từ char * để chuỗi và thay vì chỉ giả định rằng bool là điều gần gũi nhất với một con trỏ? Là lựa chọn duy nhất của tôi để làm cho một constructor char * rõ ràng mà về cơ bản không chính xác điều tương tự như các nhà xây dựng chuỗi?

+1

Tôi thường thích chuyển đổi rõ ràng hơn. Chuyển đổi ngầm định có những thứ như thế này. Xem http://stackoverflow.com/q/2346083/10077 –

+0

Tôi không chắc chắn nhưng: Cả hai chuyển đổi đều có thể (chuyển đổi con trỏ thành bool checks for null pointer). Nhưng chuyển đổi sang bool là một * chuyển đổi * tích hợp, trong khi chuỗi là một con người * xác định * convesion (thông qua ngầm c'tor). Và bây giờ nếu tôi nhớ chính xác, các bản dựng sẵn có mức độ ưu tiên cao hơn so với người dùng đã xác định. – leemes

+1

có thể trùng lặp của [C++ Phương thức quá tải không hoạt động] (http://stackoverflow.com/questions/14770252/c-method-overload-not-working) –

Trả lời

12

Nếu bạn có C++ 11 bạn có thể sử dụng một constructor ủy:

A(char const* s) : A(std::string(s)) { } 

Lý do boolean chuyển đổi-constructor được chọn thay vì một cho std::string là do chuyển đổi char const*-bool là chuyển đổi chuẩn trong khi chuyển đổi sang số std::string là chuyển đổi do người dùng xác định. Chuyển đổi chuẩn có xếp hạng cao hơn so với chuyển đổi do người dùng xác định.

3

Với

A(string("hello")); 

nó sẽ cho kết quả mong đợi.

Tại sao lại như vậy?

Đó là vì sự chuyển đổi tiêu chuẩn:

  • "hello" được hiểu là một con trỏ const char*
  • con trỏ này có thể được chuyển đổi sang một bool (Phần 4.12 của tiêu chuẩn: "Một prvalue của (...) con trỏ (...) loại có thể được chuyển đổi thành giá trị của loại bool. ")
  • chuyển đổi từ" hello "sang string không được xem xét vì mục 12.3 của tiêu chuẩn giải thích rằng" Loại chuyển đổi của các đối tượng lớp có thể được chỉ định bởi các hàm tạo và các hàm chuyển đổi. Những chuyển đổi được gọi là người dùng xác định chuyển đổi "và" chuyển đổi người dùng định nghĩa được áp dụng duy nhất mà họ rõ ràng". Bạn sẽ không có bool constructor chuyển đổi std::string sẽ được thực hiện implicitely.

Làm thế nào để có được những gì bạn mong đợi

Chỉ cần thêm các nhà xây dựng thiếu cho litterals chuỗi:

A(const char* v) 
{ 
    cout << v; // or convert v to string if you want to store it in a string member 
} 

Tất nhiên, thay vì viết lại một hàm khởi tạo từ đầu, bạn có thể chọn một đại biểu như được đề xuất bởi 0x499602D2 trong một câu trả lời khác.

+0

Vâng, nhưng tôi không muốn loại bỏ 'chuỗi (. ..) 'mọi lúc. Là lựa chọn duy nhất khác của tôi để tạo ra một hàm tạo có một 'char const *' làm đối số? – RPGillespie

+0

Có! Tôi đã hoàn thành với các giải thích bổ sung. – Christophe

2

Khi lựa chọn một phương pháp quá tải này là thứ tự mà trình biên dịch cố gắng:

  1. chính xác trận đấu
  2. Xúc tiến
  3. chuyển đổi số tiêu chuẩn
  4. Người dùng xác định khai thác

Một con trỏ không quảng bá cho bool nhưng nó chuyển đổi thành bool. A char* sử dụng toán tử std để chuyển đổi thành std::string. Lưu ý rằng nếu char* sử dụng cùng một số trong danh sách này để chuyển đổi thành cả haiboolstd::string thì sẽ không rõ ràng nên chọn trình biên dịch nào, do đó trình biên dịch sẽ gửi lỗi "quá tải không rõ ràng".

Tôi sẽ ném trọng lượng của mình sau giải pháp 0x499602D2. Nếu bạn có C++ 11, cược tốt nhất của bạn là gọi: A(char* s) : A(std::string(s)){} Nếu bạn không có C++ 11 thì tôi sẽ tạo một hàm tạo A(char* s) và trừu tượng logic của hàm tạo A(std::string) thành một phương thức và gọi phương thức đó từ cả hai nhà thầu.

http://www.learncpp.com/cpp-tutorial/76-function-overloading/

2

Gần đây tôi đã thông qua vấn đề này quá, hãy để tôi chia sẻ một cách khác.

Bạn có thể thay đổi phương thức khởi tạo bool thành unsigned char. Vì vậy, sự phân rã và ngụ ý sự biến đổi của chuỗi ký tự không xảy ra, và hàm tạo std::string diễn ra.

class A 
{ 
public: 
    A(string v) 
    { 
     cout << v; 
    } 

    A(unsigned char v) 
    { 
     cout << static_cast<bool>(v); 
    } 
}; 

int main() 
{ 
    A("Hello"); // <- Call A(string) 
    A(false); // <- Call A(unsigned char) 
} 

Bằng cách này bạn không cần phải cung cấp luôn quá tải để std::stringconst char* không phải làm cho mã sưng lên xây dựng std::string tại địa điểm cuộc gọi của khách hàng.

Tôi không tuyên bố điều đó tốt hơn, nhưng nó đơn giản hơn.

+0

Tôi đã có cùng một vấn đề, nhưng tôi tự hỏi tại sao A ("Hello"); không đưa ra cảnh báo, nhưng const char * b = "Hello"; A (b); đưa ra cảnh báo 4800: buộc giá trị để bool 'true' hoặc 'false'? –

+0

Điều này cũng làm việc cho tôi và cũng cực kỳ hữu ích với 'string_view' mới. Xem [ở đây] (https://godbolt.org/g/1uCwR2) để biết ví dụ. – Claudius

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