2010-02-23 56 views
44

Tôi đã biên soạn một chương trình C++ trong Cygwin bằng cách sử dụng g ++ và tôi đã có một lớp có hàm tạo không có đối số. Tôi đã có dòng:Không có dấu ngoặc đơn trên một hàm tạo không có đối số một tiêu chuẩn ngôn ngữ?

MyClass myObj(); 
myObj.function1(); 

Và khi cố gắng để biên dịch nó, tôi nhận được tin nhắn:

lỗi: yêu cầu cho thành viên 'Function1' trong 'myObj', mà là loại phi lớp 'MyClass()() '

Sau một ít nghiên cứu, tôi thấy rằng bản sửa lỗi là thay đổi dòng đầu tiên thành MyClass myObj;

Tôi có thể thề là tôi đã thực hiện khai báo hàm dựng rỗng với dấu ngoặc đơn trong C++ trước đây. Đây có lẽ là một hạn chế của trình biên dịch tôi đang sử dụng hay không các tiêu chuẩn ngôn ngữ thực sự nói không sử dụng dấu ngoặc đơn cho một constructor mà không có đối số?

Trả lời

49

Mặc dù MyClass myObj(); có thể được phân tích cú pháp dưới dạng định nghĩa đối tượng bằng trình khởi chạy trống hoặc khai báo hàm theo tiêu chuẩn ngôn ngữ xác định rằng sự mơ hồ luôn được giải quyết có lợi cho khai báo hàm. Trình khởi tạo dấu ngoặc đơn trống được cho phép trong các ngữ cảnh khác, ví dụ: trong biểu thức new hoặc xây dựng giá trị được khởi tạo tạm thời.

1

Tiêu chuẩn không yêu cầu dấu ngoặc đơn.

int* x = new int; 

là cú pháp pháp.

Trong trường hợp của bạn myclass myobj(); là mẫu thử nghiệm chức năng. Trong khi đó, myclass myobj; là một biến.

3

Dòng của bạn làm cho trình biên dịch nghĩ rằng bạn đang khai báo hàm có tên myObj, không có đối số và trả về MyClass. Độ phân giải không rõ ràng này thực sự gây phiền nhiễu.

10

Đây là vấn đề khá nổi tiếng và không phụ thuộc vào trình biên dịch. Về cơ bản, những gì bạn đang làm là tuyên bố một hàm trả về kiểu MyObj. Không ngạc nhiên, bạn không thể gọi hàm tạo của nó. Xem số C++ faq lite để được giải thích tốt

+0

Để mở rộng - đó chỉ là vấn đề trong một số ngữ cảnh nhất định. Viết "ném myexceptionclass();", ví dụ, và không có nhầm lẫn. Ngôn ngữ không rõ ràng trong bối cảnh Petes, nhưng các quy tắc định hướng (lý do ngôn ngữ nghiêm chỉnh không thực sự mơ hồ) chọn một giải thích. Tất nhiên các quy tắc định hướng có nghĩa là ngôn ngữ không thực sự mơ hồ - nhưng các chuyên gia phân tích vẫn nói điều đó, vì vậy tôi cũng được phép! Các quy tắc định hướng phổ biến nhất trong nhiều ngôn ngữ là ưu tiên toán tử và khả năng kết hợp - C và C++ có nhiều mơ hồ hơn, và kết quả là có một số vấn đề lạ. – Steve314

44

Đây được gọi là vấn đề phân tích cú pháp gây tranh cãi nhất. Khi phân tích cú pháp thấy

MyClass myObj(); 

Nó nghĩ rằng bạn đang định nghĩa một hàm gọi là myObj mà không có tham số và trả về một MyClass.

Để có được xung quanh nó, sử dụng:

MyClass myObj; 
+0

Xin chào, ngoài việc được phân bổ trên stack và heap tương ứng, có bất kỳ sự khác biệt nào giữa 'MyClass obj' và' MyClass * obj = new MyClass() 'không? – SexyBeast

+1

Một vài. Cái đầu tiên khai báo 'obj' như một đối tượng kiểu' MyClass', và sẽ tự động được giải phóng khi phạm vi thoát. Câu lệnh thứ hai khai báo 'obj' là một đối tượng kiểu' MyClass * ', phải được giải phóng thủ công và sẽ có sẵn sau khi thoát khỏi phạm vi. –

+0

Yeah yeah, đó chính xác là kết quả của việc phân bổ trên stack và heap tương ứng, phải không? – SexyBeast

4
MyClass myObj(); 

Đó là phân tích cú pháp như một khai báo hàm, hàm được gọi myObj, không có đối số và trả về MyClass đối tượng. Tôi chưa bao giờ thấy một trình biên dịch chấp nhận điều đó. Mặt khác, MyClass* myPtr = new MyClass(); là chấp nhận được, có thể khiến bạn bối rối?

18

Tôi tìm thấy điều này trong tiêu chuẩn C++ (§8.5.8):

An object whose initializer is an empty set of parentheses, i.e.,(), shall be value-initialized.

[Note: since() is not permitted by the syntax for initializer,

X a(); 

is not the declaration of an object of class X, but the declaration of a function taking no argument and returning an X. The form () is permitted in certain other initialization contexts (5.3.4, 5.2.3, 12.6.2). —end note ]

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