2011-12-12 33 views
11

thể trùng lặp:
Why is it an error to use an empty set of brackets to call a constructor with no arguments?C++ constructor ma quái

Cho phép có mã này

class Foo { 
    Foo(int) { } 
}; 

Sau đó, chúng tôi có có kết quả:

int main() { 
    Foo f1 = Foo(5); // 1: OK, explicit call 
    Foo f2(5); // 2: OK, implicit call 
    Foo f3(); // 3: no error, "f3 is a non-class type Foo()", how so? 
    Foo f4(f1); // 4: OK, implicit call to default copy constructor 
    Foo f5; // 5: expected error: empty constructor missing 
} 

Bạn có thể giải thích những gì đang xảy ra trong trường hợp ?

+13

tìm kiếm: vexing parse – Nim

+0

@Nim: Phải là câu trả lời. –

+0

Cũng lưu ý rằng ví dụ 5 đang làm những gì được mong đợi ví dụ 3 để làm và gọi hàm khởi tạo mặc định. – Joe

Trả lời

8

Foo f3(); khai báo hàm có tên f3, với kiểu trả về là Foo.

+0

Ah, tất nhiên! Tôi đã quá tập trung vào các nhà thầu ... –

12

Dòng thứ ba được phân tích cú pháp như khai báo hàm không nhận đối số và trả về một Foo.

2

Bạn đã xác định một hàm có tên là f3 trả về một foo trong trường hợp 3. Trong trường hợp 5, bạn không có hàm tạo mặc định nào, do đó bạn gặp lỗi.

5

C++ có quy tắc rằng nếu một câu lệnh có thể được hiểu là khai báo hàm, nó được diễn giải theo cách này.

Do đó cú pháp Foo f3(); thực sự khai báo hàm không nhận đối số và trả về Foo. Làm việc này bằng cách viết Foo f3;, nó sẽ gọi hàm tạo mặc định (nếu có, dĩ nhiên).

4
  • f1 gọi constructor sao chép sau khi một cuộc gọi rõ ràng thì bạn đã nhầm về vấn đề này một
  • f2 là một cuộc gọi constructor rõ ràng // bạn đã sai ở đây quá
  • f3 tuyên bố một hàm
  • f4 là một lần nữa hàm tạo bản sao, như f1 // bạn đang ở đây
  • f5 sẽ gọi hàm tạo mặc định // bạn đang ở đây một lần nữa
+0

'Foo f6 = 5;' sẽ bởi một cuộc gọi hàm tạo ngầm? IIRC. –

+0

@Douglas: Vâng, điều đó sẽ đúng. – Xeo

3

Đây không phải là những gì bạn nghĩ rằng đó là:

Foo f3(); 

Bạn có thể nghĩ rằng đây là một cuộc gọi rõ ràng của các nhà xây dựng mặc định, nhưng nó không phải. Nó thực sự là một tuyên bố của một hàm có tên là f3, không có tham số và trả về giá trị Foo theo giá trị.

Điều này được phân tích cú pháp dưới dạng khai báo hàm chứ không phải gọi hàm dựng được gọi là Most Vexing Parse.

+0

Không, không. MVP là khi bạn cung cấp các đối số và nó vẫn trông giống như một khai báo hàm. Đây không phải là MVP, nó chỉ là lập trình viên ngớ ngẩn –