2012-06-27 2 views
21

Vì vậy, về cơ bản mã này:Tại sao hàm tạo bản sao được gọi thay vì hàm tạo chuyển đổi?

class A { 
}; 
class B { 
    B (const B& b) {} 
public: 
    B(){} 
    B (const A& a) {} 
}; 

int main() 
{ 
    A a; 
    B b1(a); //OK 
    B b2 = a; //Error 
} 

chỉ tạo ra một lỗi cho B b2 = a. Và lỗi đó là

error: ‘B::B(const B&)’ is private

Tại sao nó cố gắng gọi hàm tạo bản sao bên cạnh hàm tạo chuyển đổi trực tiếp?

Rõ ràng từ thông báo lỗi rằng tạm thời B được tạo sau đó được sử dụng để sao chép-xây dựng, nhưng tại sao? Cái này ở đâu trong tiêu chuẩn?

+0

Is câu hỏi của bạn liên quan đến cơ hội này [http://stackoverflow.com/questions/11221242/is-this-a-copy-constructor)? :) –

+0

@EitanT sao bạn biết? –

+0

Bởi vì tôi đã xem xét câu hỏi đó vài phút trước :) –

Trả lời

13
B b2 = a; 

này được gọi là Copy Initialization.

Nó THH sau:

  1. Tạo một đối tượng kiểu B từ a bằng cách sử dụng B (const A& a).
  2. Sao chép đối tượng tạm thời được tạo thành b2 bằng cách sử dụng B (const B& b).
  3. Phá hủy đối tượng tạm thời bằng cách sử dụng ~B().

Các lỗi bạn nhận được không phải là ở bước 1 nhưng thay vì ở bước 2.

Where is this in the standard?

C++ 03 8,5 Initializers
Para 14:

....
— If the destination type is a (possibly cv-qualified) class type:
...
...
— Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3). If the conversion cannot be done or is ambiguous, the initialization is ill-formed. The function selected is called with the initializer expression as its argument; if the function is a constructor, the call initializes a temporary of the destination type. The result of the call (which is the temporary for the constructor case) is then used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization. In certain cases, an implementation is permitted to eliminate the copying inherent in this direct-initialization by constructing the intermediate result directly into the object being initialized; see 12.2, 12.8.

+1

Nhưng tại sao không trực tiếp sử dụng trình tạo chuyển đổi? –

+0

@LuchianGrigore: Lỗi này là * sau khi * chuyển đổi đã được thực hiện, trong quá trình xây dựng bản sao. Cuộc gọi để sao chép hàm tạo có thể được elided là tốt, nhưng điều đó phụ thuộc vào trình biên dịch. Ngoài ra, vẫn còn các nhà xây dựng bản sao cần phải được có thể truy cập. –

+0

Vâng, tôi hiểu điều đó (và tôi biết họ phải được nhìn thấy bất kể họ có được gọi hay không). Nhưng tại sao nó không chỉ làm điều đó trong một bước? Tại sao cần một tạm thời 'B'? –