2015-10-18 20 views
10

Chỉnh sửa: Tôi đã định dạng lại bài đăng để rõ ràng hơn.Tại sao thêm hai chuỗi ký tự không sử dụng toán tử + (const string &, const string &)?

Tại sao công việc này:

struct A {}; 

struct B { 
    B(A){} 
}; 

void operator+(const B&, const B&) {} 

int main() 
{ 
    A a1, a2; 
    a1 + a2; 
} 

và điều này không?

struct B { 
    B(const char*){} 
}; 

void operator+(const B&, const B&) {} //error: invalid operands of types 'const char [6]' and 'const char [6]' to binary 'operator+'| 

int main() 
{ 
    "Hello" + "world"; 
} 

Về cơ bản, trong ví dụ đầu tiên a1a2 cả chuyển đổi sang B đối tượng thông qua việc chuyển đổi ngầm và sử dụng operator+(const B&, const B&) thêm.

Tiếp theo từ ví dụ này, tôi lại có thể ngờ "Hello""world" chuyển đổi sang B đối tượng, một lần nữa thông qua các nhà xây dựng ngầm, và sử dụng operator+(const B&, const B&) để thêm vào nhau. Thay vào đó có lỗi, cho biết các chuỗi kiểu C không cố gắng chuyển đổi do người dùng xác định thành B để thêm. Tại sao điều này? Có một tài sản cơ bản nào ngăn cản điều này?

+1

Bạn không liên quan đến 'std :: string' với' "ngăn xếp" + "tràn"; '. –

+1

@ πάνταῥεῖ Ông nhận thức được điều đó, câu hỏi đặt ra là tại sao việc chuyển đổi ẩn thành 'std :: string' không khắc phục điều đó cho anh ta. –

+1

Ví dụ tối thiểu của bạn là một chút tắt vì 'const char *' không có toán tử chuyển đổi, nhưng việc chuyển đổi xảy ra thông qua hàm tạo 'std :: string'. [Điều này] (http://coliru.stacked-crooked.com/a/1c4aafeb95886b92) sẽ là một chút apt hơn. –

Trả lời

5

Trong ví dụ đầu tiên của bạn, độ phân giải quá tải là cho phép để tìm bạn operator+:

[C++14: 13.3.1.2/2]:If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator.[..]

[C++14: 13.3.2/1]:From the set of candidate functions constructed for a given context (13.3.1), a set of viable functions is chosen, from which the best function will be selected by comparing argument conversion sequences for the best fit (13.3.3). The selection of viable functions considers relationships between arguments and function parameters other than the ranking of conversion sequences.

[C++14: 13.3.2/2]: First, to be a viable function, a candidate function shall have enough parameters to agree in number with the arguments in the list.

  • If there are m arguments in the list, all candidate functions having exactly m parameters are viable.
  • [..]

[C++14: 13.3.2/3] : Second, for F to be a viable function, there shall exist for each argument an implicit conversion sequence (13.3.3.1) that converts that argument to the corresponding parameter of F .[..]

(bạn có thể kiểm tra các từ ngữ cho "chuỗi chuyển đổi ngầm" chính mình để thấy rằng tôi operator+ cuộc gọi s cho phép; các quy tắc quá rườm rà để đảm bảo tái tạo đúng nguyên văn ở đây.)

Tuy nhiên, trong ví dụ thứ hai của bạn, độ phân giải quá tải bị hạn chế để một cơ chế số học Ngoài cơ bản (một trong đó không được định nghĩa cho const char[N] hoặc const char*), có hiệu quả giới hạn bất kỳ operator+ chức năng được xem xét:

[C++14: 13.3.1.2/1]:If no operand of an operator in an expression has a type that is a class or an enumeration, the operator is assumed to be a built-in operator and interpreted according to Clause 5.

[C++14: 5.7/1]:[..]For addition, either both operands shall have arithmetic or unscoped enumeration type, or one operand shall be a pointer to a completely-defined object type and the other shall have integral or unscoped enumeration type. [..]

[C++14: 5.7/3]: The result of the binary + operator is the sum of the operands.

+2

Câu trả lời hay.Cảm ơn bạn và @BaummitAugen đặc biệt là để giúp đỡ với điều này (và tất cả mọi người khác quá). – Silversonic

+0

@Silversonic: Thật thú vị! #Có chuyện gì với tôi vậy –

2

1. Giải thích lỗi biên dịch của bạn:

Lý do bạn không thể nối hai xâu bằng cách sử dụng '+' nhà điều hành,
là vì xâu chỉ đơn giản là mảng các ký tự, và bạn có thể' t nối hai mảng.

Mảng sẽ được chuyển đổi hoàn toàn thành con trỏ của phần tử đầu tiên của chúng.

Hoặc như tiêu chuẩn mô tả nó:

[conv.array]
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

Những gì bạn đang thực sự làm trong ví dụ trên,
đang cố gắng thêm hai con trỏ char const với nhau, và đó là điều không thể.


2. Tại sao các xâu không mặc nhiên chuyển đổi:

Kể từ mảng và con trỏ là loại cơ bản, bạn không thể cung cấp một nhà điều hành trò chuyện ngầm như bạn đã làm trong ví dụ lớp học của bạn .

Điều chính cần ghi nhớ là std::string biết cách thực hiện trong char[], nhưng char[] không biết cách trở thành một std::string. Trong ví dụ của bạn, bạn đã sử dụng B, thay thế cho char[], nhưng bạn cũng đã cho nó khả năng tự chuyển đổi thành A.


3. Lựa chọn thay thế:

Bạn có thể ghép xâu bằng cách bỏ đi các nhà điều hành cộng.

"stack" "overflow"; //this will work as you indented 

Tùy chọn, bạn có thể làm cho "chồng" một std :: string, và sau đó sử dụng std :: string của quá tải '+' điều hành:

std::string("stack") + "overflow"; //this will work 
+3

Điều này không giải thích tại sao chuyển đổi ẩn thành 'std :: string' không xảy ra. –

+2

Khi @BaummitAugen đề cập đến, câu trả lời này không giải thích tại sao cả toán hạng 'char *' không thể được chuyển đổi thành 'chuỗi' bởi các chuyển đổi do người dùng định nghĩa và' toán tử + (chuỗi ký tự &, const string &) '. – Silversonic

+0

Bạn có thể trích dẫn phần có liên quan của tiêu chuẩn C++ không? Bởi vì có một câu trả lời và nó hoàn toàn khác (dựa trên chuỗi là một mẫu). –

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