2012-12-18 28 views
6

Tôi chưa bao giờ gặp phải điều này trước đây trong C++ nhưng thật kỳ lạ khi nó vẫn biên dịch nhưng không làm những gì tôi mong đợi. Ai đó có thể cho tôi biết nó làm gì không? Vui lòng xem mã, biết thêm thông tin sau.Lập tức một lớp bằng C++: Lỗi cú pháp lạ

#include <iostream> 
using namespace std; 

class Test{ 
    public: 
     Test(); 
}; 

Test::Test(){ cout << "ctor" << endl; } 

int main(void){ 

    Test t(); // this compiles but doesn't call the constructor 

    return(0); 
} 

Nó sẽ biên dịch, nhưng nếu tôi cố gắng sử dụng "t" thì không. Tôi chỉ phụ thuộc vào chức năng của hàm tạo và mã của tôi không hoạt động như mong đợi. Giải pháp là để mất dấu ngoặc đơn "Test t();" để "Kiểm tra t;". Câu hỏi của tôi là những gì đang xảy ra trong "Test t();" Ví dụ, và trình biên dịch nghĩ gì đang xảy ra mà nó cho phép nó biên dịch.

+5

Tra cứu phân tích cú pháp gây nhiều tranh cãi nhất. – chris

+1

Chào mừng bạn đến với Rite of Passage. –

+0

Câu hỏi là ... trình biên dịch có biết bạn đang mong đợi điều gì không? :) – Carl

Trả lời

5

Đây là Most Vexing Parse. Về cơ bản, theo các quy tắc phân tích cú pháp C++, những gì bạn có không phải là đối tượng thuộc loại Test có tên t, mà đúng hơn là khai báo hàm cho hàm t, không lấy đối số và trả về Test.

Ngẫu nhiên, clang ++ thực sự nhận ra tình trạng này và phát ra cảnh báo, cho bạn biết rằng điều này có thể không làm những gì bạn muốn.

+0

Chúng ta có thể khai báo/định nghĩa các hàm trong các hàm khác không? Tôi cho là không? –

+0

@KarthikT: Tôi không nghĩ rằng bạn có thể xác định các hàm lồng nhau trong C++, nhưng bạn chắc chắn có thể khai báo chúng. Ví dụ, điều này hoạt động tốt: 'int main() {void foo(); foo(); } void foo() {std :: cout << "foo" << std :: endl; } ' –

+0

@Karthik: Các hàm có thể được * khai báo * bên trong các hàm khác. Đây là trường hợp từ C. – AnT

1

Đây là sự cố thường gặp được đặt tên là phân tích cú pháp gây tranh cãi nhất. Đường dây của bạn Test t(); có thể được diễn giải theo một trong hai cách.

  1. Nó có thể khai báo một biến t đó là loại Test
  2. Nó có thể khai báo một hàm t(), mà trả về một giá trị Test và không có đối số

Chuẩn C++ không may đòi hỏi trình biên dịch để xem xét giải pháp thay thế thứ hai, đây là một cách phân tích cú pháp khá rõ ràng.

Cách dễ nhất để sửa chữa rằng phân tích là để thoát khỏi dấu ngoặc và đơn giản tuyên bố biến của bạn như vậy:

Test t; // Will call the default constructor