2012-10-17 37 views
8

Đang cố gắng để biên dịch đoạn mã sau vào trình biên dịch khác nhau mang lại cho tôi hai kết quả khác nhau:Có thể một thành viên của một lớp được đặt tên giống với tên của nó (lớp khác) không?

struct S{}; 
struct T{S S;}; 
int main(){} 

Như bạn có thể thấy, bên trong T, tôi có một đối tượng có tên giống như các lớp được định nghĩa trước S.


On GCC 4.7.2, I get the following error liên quan đến việc kê khai S S; bên T:

error: declaration of 'S T::S' [-fpermissive]
error: changes meaning of 'S' from 'struct S' [-fpermissive]

Tuy nhiên, di chuyển nó bên ngoài của lớp (hoặc vào main) works fine:

struct S{}; 
S S; 
int main(){} 

Lỗi chính xác có nghĩa là gì?


Trong Visual Studio 2012, toàn bộ việc biên dịch và chạy mà không có bất kỳ lỗi nào. Dán nó vào this Clang 3.0 compiler cũng không có lỗi.

Điều gì là đúng? Tôi có thể thực sự làm điều này hay không?

+0

Ah, tôi hiểu - tôi đã đọc sai chẩn đoán. – ildjarn

+1

@ildjarn, Đó là một lá cờ khá lạ. Dường như nó hoạt động ngược lại. Thông thường, cờ chịu trách nhiệm cảnh báo xuất hiện trong dấu ngoặc vuông. – chris

+2

Chỉ cần không. Vấn đề ở đây là gì? Nhầm lẫn? Lưu ý rằng sau khi bạn đã làm điều đó, bạn không còn có thể tham chiếu đến kiểu 'S' trong các hàm thành viên mà không đủ điều kiện rõ ràng vùng tên ... –

Trả lời

14

gcc là đúng, từ [3.3.7 Lớp Phạm vi]

A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

Tuy nhiên, lưu ý rằng no diagnostic is required, vì vậy tất cả các trình biên dịch được phù hợp.

Lý do là do phạm vi hoạt động của lớp. Khi bạn viết S S;S hiển thị trong toàn bộ toàn bộ lớp và thay đổi ý nghĩa khi bạn sử dụng S.

struct S{}; 
struct T{ 
    void foo() 
    { 
     S myS; // Not possible anymore because S refers to local S 
    } 
    S S; 
}; 
+1

Lý do cơ bản, IIRC, là cho phép định nghĩa các hàm thành viên lớp trong lớp. Tra cứu tên bên trong chúng sẽ rất sôi nổi nếu ý nghĩa của tên thay đổi trong một lớp. (Nó đã đủ cứng). – MSalters

+0

Ví dụ tương tự hoạt động hoàn hảo với ngữ nghĩa chính xác trong C#. '' '' '' '' 'S cũng có thể sử dụng với ngữ nghĩa chính xác. C# có thể phân biệt ngữ cảnh trong đó 'S' được sử dụng và không rõ tại sao trình biên dịch C++ không thể làm như vậy. – ceztko

6

Mã này không đúng định dạng, không yêu cầu chẩn đoán. Giống như chẩn đoán nói, nếu khai báo sử dụng tên và tên có ý nghĩa khác với nó sẽ có khi tra cứu ở cuối định nghĩa lớp, thì programm bị biến dạng, không cần chẩn đoán.

+0

Một ngày khác, nơi tôi đang cải thiện bản thân mình! +1 –

6

@JesseGood cung cấp một câu trả lời hoàn chỉnh, nhưng nếu bạn thực sự muốn làm điều này mà không cần bất kỳ lỗi, bạn có thể sử dụng tên đầy đủ loại và nó sẽ làm việc như sau:

struct S {}; 
struct T { ::S S; }; 
int main() {return 0;} 

Không không có lỗi, kể từ S trong lớp học của bạn là T::S và loại của nó là ::S!

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