2017-06-10 16 views
8

Tôi có lớp sau đây:Xây dựng một đối tượng với một chuỗi chữ

#include <iostream> 
#include <string> 

using namespace std; 

class CLS 
{ 
    int value; 
    string str_value; 

public: 

    CLS(int param) { value = param; } 

    CLS(string param) 
    { 
     str_value = param; 
    } 
}; 

int main() 
{ 
    CLS a(2); 
    CLS b = 3; 
    CLS c("4"); 
    CLS d = "5"; // Error: invalid conversion from 'const char*' to 'int' 
} 

Tôi đã tìm kiếm cho lý do tại sao nó là lỗi không có may mắn.

Có đúng để xây dựng bằng chuỗi chữ không? nếu không, tại sao? nếu có, có gì sai với mã của tôi?

Tôi đang sử dụng gcc 5.3 với Mã :: Khối 16.1.

+5

Tôi lưu ý rằng điều này được xây dựng tốt theo VS2017. Điều đáng ghi nhớ là một chuỗi ký tự không giống như một chuỗi 'std :: string'. – Rook

+0

Đó có phải là một ví dụ đầy đủ không? Có tiêu đề nào không? 'Chuỗi' trong trường hợp của bạn là gì? – ArturFH

+0

@Artur R. Czechowski - Đây là một ví dụ đầy đủ (tôi đã thêm tiêu đề). 'chuỗi' phải là' std :: string' tôi đoán. –

Trả lời

11

Lúc đầu, "4" không phải là std::string, là const char[2]. Sau đó,

CLS c("4");direct initialization, các nhà thầu của CLS sẽ được kiểm tra để khởi tạo c. CLS::CLS(string) được chọn tại đây, vì const char[] có thể được chuyển đổi hoàn toàn thành std::string qua chuyển đổi do người dùng xác định (nghĩa là std::string::string(const char*)).

CLS d = "5";copy initialization,

(tôi nhấn mạnh)

  • Nếu T là một kiểu lớp, và phiên bản cv-không đủ tiêu chuẩn của các loại other không phải là T hoặc có nguồn gốc từ T, hoặc nếu T là loại không phải loại, nhưng loại other là loại lớp, chuỗi chuyển đổi do người dùng xác định có thể chuyển đổi từ loại other đến T (hoặc loại có nguồn gốc từ T nếu T là loại lớp và chức năng chuyển đổi khả dụng) được kiểm tra và chọn loại tốt nhất thông qua độ phân giải quá tải.

Điều đó có nghĩa trình tự chuyển đổi người dùng xác định là cần thiết để chuyển đổi const char[2]-CLS. Thậm chí const char[] có thể được chuyển đổi thành std::stringstd::string có thể được chuyển đổi thành CLS, nhưng chỉ một chuyển đổi do người dùng xác định được phép trong một implicit conversion sequence. Đó là lý do tại sao nó bị từ chối.

(tôi nhấn mạnh)

chuỗi chuyển đổi ngầm bao gồm những điều sau đây, theo thứ tự này:

1) không hoặc một chuỗi chuyển đổi tiêu chuẩn;
2) 0 hoặc một chuyển đổi do người dùng xác định;
3) không hoặc một chuỗi chuyển đổi chuẩn.

BTW: Nếu bạn thay đổi thành sử dụng std::string làm biểu thức khởi tạo rõ ràng nó sẽ hoạt động tốt. ví dụ.

CLS d = std::string{"5"}; // pass a temporary std::string constructed from "5" to the constructor of CLS 

using namespace std::string_literals; 
CLS d = "5"s;    // "5"s is a string literal of type std::string (supported from C++14) 
+0

Vì vậy, yêu cầu chuyển đổi do người dùng xác định cũng áp dụng cho chuyển đổi tiềm ẩn? Vì nếu không 'const char [2]' -> ngầm định 'const char *' -> do người dùng định nghĩa 'std :: string', phải không? – Rakete1111

+0

@ Rakete1111 (1) Có, chỉ một chuyển đổi do người dùng xác định được phép trong một trình tự chuyển đổi tiềm ẩn; (2) Tôi không thể có được ý định của bạn, 'const char [2]' -> 'const char *' không phải là chuyển đổi do người dùng xác định mà là chuyển đổi tiêu chuẩn có thể nhiều hơn một lần. – songyuanyao

+0

Vâng, đó là điểm chính xác của tôi: Nếu chỉ có 1 người dùng xác định chuyển đổi được cho phép, sau đó 'const char [2]' -> 'const char *' không đếm, và 'std :: string' của constructor có thể được sử dụng (là 1 chuyển đổi do người dùng xác định). Nhưng tại sao nó không được phép? – Rakete1111

8
CLS a(2); 
CLS b = 3; 
CLS c("4"); 
CLS d = "5"; 

ac được khởi tạo với direct initialisation. bd sử dụng tay khác copy initialisation.

Sự khác biệt là đối với bản sao khởi động tìm kiếm trình biên dịch cho một (duy nhất) sử dụng được xác định chuyển đổi từ (trong trường hợp d) char const * (đây là một chút không chính xác, xem kết thúc của câu trả lời) để CLS, trong khi cho khởi động trực tiếp tất cả các nhà thầu được thử, trong đó CLS(std::string) có thể được sử dụng bởi vì có sẵn một chuyển đổi std::string(char const *).

Chi tiết:

"5" là (C) chuỗi chữ. Đó là loại là char const [2]. Vì vậy, trước tiên, một chuyển đổi do người dùng xác định từ loại đó thành CLS được tìm kiếm. Vì không tìm thấy gì, chuyển đổi tiêu chuẩn từ Type[N] thành Type * (với Type = char constN = 2) được áp dụng, dẫn đến char const *. Sau đó trình biên dịch sẽ cố gắng tìm một chuyển đổi do người dùng xác định từ đó thành CLS. Bởi vì nó không tìm thấy một, và không có chuyển đổi tiêu chuẩn hơn nó có thể thử có sẵn, biên dịch không thành công.

+0

Bạn có nghĩa là "[...] người dùng xác định chuyển đổi từ (trong trường hợp' d') 'char const []' [...] "? '" 5 "' có thể phân rã thành 'const char *', nhưng nó là 'const char [2]'. – Rakete1111

+0

@ Rakete1111 có bạn đi, tôi ban đầu rời sâu ra khỏi câu trả lời để giữ cho nó tập trung vào các chuyển đổi. –

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