2016-01-25 16 views
5

Tôi tự hỏi, tại sao nó không được phép viết:Tuyên bố và khai báo có định nghĩa. Tại sao điều này không được phép?

struct foo {  
    void bar();          // declaration 
    void bar(){std::cout << "moo" << std::endl;} // declaration + definition 
}; 

Chức năng được khai báo hai lần (tôi nghĩ đây là ok) và xác định một lần. Tuy nhiên, trình biên dịch của tôi phàn nàn về:

decldef.cxx:7:10: error: 'void foo::bar()' cannot be overloaded 

Tại sao nó không được phép?

Tại sao trình biên dịch của tôi (g ++ 4.7.2) giải thích điều này là quá tải?

PS: Tôi biết cách viết "đúng cách", nhưng tôi chỉ muốn biết, tại sao ở trên là sai.

+0

Thật vậy, nhưng câu hỏi này không chạy sâu hơn thế, theo ý kiến ​​của tôi ít nhất. Ví dụ, nếu 'struct' được thay thế bằng' namespace' thì mã đó là hợp lệ. – Bathsheba

+0

Câu hỏi hay, thực sự.Phần "+ định nghĩa" thực sự không liên quan; ngay cả một tuyên bố lặp đi lặp lại với chữ ký giống hệt nhau không được phép ở đây. – mindriot

Trả lời

10

Từ §9.3

Trừ các định nghĩa hàm thành viên xuất hiện bên ngoài của một định nghĩa lớp, và ngoại trừ các chuyên ngành rõ ràng của các hàm thành viên của lớp mẫu và chức năng thành viên các mẫu (14,7) xuất hiện bên ngoài của định nghĩa lớp, chức năng thành viên không được được redeclared.

Bên cạnh đó, trong trường hợp này các báo cáo cũng có thể rơi hôi của:

Một hàm thành viên có thể được định nghĩa (8.4) trong định nghĩa các lớp học, trong trường hợp này nó là một chức năng thành viên inline (7.1.2) hoặc có thể được xác định ngoài định nghĩa lớp nếu có đã được khai báo nhưng không được xác định trong định nghĩa lớp.

Khi khai báo đầu tiên không khai báo hàm là inline. Định nghĩa thứ hai ngầm ẩn.

Tuy nhiên, phản hồi đó dường như kém thuyết phục hơn.

+3

Nếu đây là câu trả lời đúng, tại sao 'struct foo {void bar(); void bar(); }; 'thất bại với thông báo lỗi rất giống nhau? – DevSolar

+0

@DevSolar được cập nhật để trả lời câu hỏi của bạn. –

+4

Phần thứ hai bạn trích dẫn là những gì thực sự trả lời câu hỏi; "_a chức năng thành viên sẽ không được redeclared_". Sự khác biệt nội tuyến không thực sự quan trọng trong ngữ cảnh này. – mindriot

5

Hàm được khai báo hai lần (tôi nghĩ điều này là ok) và được xác định một lần.

Điều này độc lập với việc bạn có xác định hàm lần thứ hai hay không. Vấn đề là bạn đang tuyên bố chức năng hai lần và đó là không phải OK.

này không biên dịch, hoặc, với thông báo lỗi tương tự:

struct foo { 
    void bar(); 
    void bar(); 
}; 

Bạn không thể khai báo lại các chức năng tương tự với cùng một danh sách tham số bên trong định nghĩa lớp:

'void foo::bar()' cannot be overloaded with 'void foo::bar()'. 
+0

Thật vậy. Vì vậy, có một tuyên bố rõ ràng trong tiêu chuẩn một nơi nào đó nói rằng _why_ điều này là không được phép? Theo ý kiến ​​của tôi, thông báo lỗi của trình biên dịch là tốt nhất gây hiểu lầm, vì đây không phải là thực sự quá tải ... – mindriot

+0

@mindriot: Richard Hodges có (đã chỉnh sửa) báo giá. Tôi không có một bản sao của tiêu chuẩn C++ trong tầm tay. – DevSolar

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