2015-08-27 14 views
9

Tôi mong đợi mã bên dưới để in Test::Test(string,string,bool), tuy nhiên nó in Test::Test(string,bool). Tại sao nó gọi hàm tạo chỉ nhận một tham số chuỗi khi hai tham số được cung cấp? Chắc chắn một chuỗi không thể được chuyển đổi thành một bool ...? Tôi đã thử thêm từ khóa rõ ràng nhưng nó không giúp ích gì. Mã số cũng ở http://ideone.com/n3tep1.Nhà xây dựng sai C++ được gọi là

#include <iostream> 
#include <string> 

using namespace std; 

class Test 
{ 
public: 

    Test(const string& str1, bool flag=false) 
    { 
     cout << "Test::Test(string,bool)" << endl; 
    } 

    Test(const string& str1, const string& str2, bool flag=false) 
    { 
     cout << "Test::Test(string,string,bool)" << endl; 
    } 
}; 

int main() 
{ 
    Test* test = new Test("foo", "bar"); 
} 
+7

' "thanh"' không phải là một 'std :: chuỗi', nó là một 'const char * ', và một con trỏ có thể được chuyển đổi hoàn toàn thành một' bool', và chuyển đổi đó phải được ưu tiên hơn hàm tạo 'std :: string (const char *)'. – clcto

+0

Phiên bản đầu tiên là một kết hợp tốt hơn, thử thử nghiệm mới ("foo", std :: string ("bar")) – Melkon

+6

Trên một ghi chú có liên quan, bạn thường không muốn sử dụng 'mới' rất thường xuyên trong mã C++ . Các biến ngăn xếp được ưu tiên khi có thể. Chỉ cần một đầu lên kể từ khi bạn nói rằng bạn đã đi xa một lúc. – dandan78

Trả lời

0

Tôi hy vọng rằng nếu bất cứ điều gì thì trình biên dịch sẽ phàn nàn về các hàm không rõ ràng. Lý do tôi mong đợi rằng, và bạn nhận được hàm tạo sai được gọi, là sử dụng một kết quả chuỗi ký tự trong một con trỏ, và con trỏ có thể được chuyển đổi hoàn toàn thành một giá trị boolean.

Trong trường hợp này trình biên dịch dường như nghĩ rằng chuyển đổi boolean là kết hợp tốt hơn so với chuyển đổi thành một số std::string.

+0

Tôi đã bật các tùy chọn g ++ sau, nhưng không có cảnh báo: -pantic -Wall -Wextra. – user1775138

+1

Chuyển đổi boolean * là * đối sánh tốt hơn so với chuyển đổi thành 'std :: string'. – Barry

6

Loại đối số được sử dụng để xây dựng Testchar const[4].

char const[4] phân rã thành char const* và phải được chuyển đổi thành bool hoặc std::string const& để thực hiện cuộc gọi hàm rõ ràng.

Một con trỏ có thể được chuyển đổi thành bool bằng quy tắc chuyển đổi chuẩn.

A char const* có thể được chuyển đổi thành std::string const& bằng quy tắc chuyển đổi do người dùng xác định.

Cho rằng, chuyển đổi từ char const*, con trỏ, đến bool được coi là kết hợp tốt hơn so với chuyển đổi từ char const* thành std::string const&.

Do đó, cuộc gọi sẽ giải quyết cho hàm tạo đầu tiên.

2

"bar" thuộc loại char const [4] và chuyển đổi từ đó thành bool là chuỗi chuyển đổi chuẩn, trong khi chuyển đổi thành std::string là chuyển đổi do người dùng xác định. Cái cũ luôn được ưu tiên hơn cái sau.

Từ N3337, [conv]/1

chuyển đổi tiêu chuẩn là chuyển đổi tiềm ẩn với ý nghĩa built-in. Khoản 4 liệt kê tập hợp đầy đủ các chuyển đổi đó. Một chuỗi tiêu chuẩn chuyển đổi là một chuỗi các chuyển đổi chuẩn theo thứ tự sau:
        - Một hoặc không có chuyển đổi từ tập sau: giá trị trái-to-rvalue chuyển đổi, mảng-to-con trỏ chuyển đổi, và chuyển đổi hàm-to-con trỏ.
        - Một hoặc không có chuyển đổi từ tập sau: chương trình khuyến mãi không thể thiếu, xúc tiến điểm, không thể thiếu chuyển đổi, chuyển đổi dấu chấm động, nổi không thể thiếu chuyển đổi, chuyển đổi con trỏ, con trỏ đến chuyển đổi thành viên nổi, và chuyển đổi boolean.
        - Không hoặc một chuyển đổi đủ điều kiện.

Trong ví dụ của bạn, chuỗi chuyển đổi chuẩn bao gồm chuyển đổi mảng-thành-con trỏ và chuyển đổi boolean.

[conv.array]/1

Một vế trái hoặc rvalue kiểu “mảng của N T” hoặc “mảng không rõ ràng buộc của T” có thể được chuyển đổi sang một prvalue kiểu “con trỏ đến T ”. Kết quả là một con trỏ đến phần tử đầu tiên của mảng.

[conv.bool]/1

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 loại 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. ...

Vì vậy, Test("foo", "bar") dẫn đến cuộc gọi đến hàm tạo Test(const string&, bool) thay vì hàm khác.


Một cách để kích hoạt một cuộc gọi đến constructor khác sẽ được sử dụng string_literals

using namespace std::literals::string_literals; 
Test("foo", "bar"s); // calls Test(const string&, const string&, bool) 
//    ^
Các vấn đề liên quan