2012-04-07 30 views
32

Tôi vô tình tình cờ tìm thấy điều này trong một trong các mã nguồn mà tôi đã xem. Vì vậy, tôi đưa ra một ví dụ nhỏ hơn tương tự ở đây.Nhà điều hành giải pháp phạm vi

Trong tập tin test.h:

#include<iostream> 

class test{ 
    int i; 
public: 
    test(){} 
    //More functions here 
}; 

Trong tập tin test.cpp:

#include "test.h" 

int main() 
{ 
    test test1; 
    test::test test2; 
    test::test::test test3; 
    return 0; 
} 

Trước hết, là có một lý do để tuyên bố test2 như vậy? Thứ hai, mã này biên dịch tốt trong phiên bản g ++ 4.4.3 và các phiên bản thấp hơn. Có một cái gì đó trong tiêu chuẩn C + +, nói rằng, các nhà khai thác độ phân giải phạm vi được bỏ qua khi không có cần phải giải quyết phạm vi?

Trả lời

41

Mã này không hợp lệ.

Đó là lỗi trong g + + mà nó chấp nhận mã. Xem "g++ does not treat injected class name correctly." Lỗi đã được giải quyết như cố định trong năm 2009, do đó, nó sẽ được sửa trong bất kỳ phiên bản g ++ nào gần đây.

+0

Haha, thậm chí tốt hơn + 1. Nó khiến tôi bối rối. –

+0

Đồng ý, +1 thực sự tôi bị cám dỗ để viết một câu trả lời chỉ để làm rõ. Chúc mừng James! –

+2

+1 Nice find ... –

16

Để làm rõ tình hình, theo quy định tại §9/2:

A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name. For purposes of access checking, the injected-class-name is treated as if it were a public member name.

Tuy nhiên, theo quy định tại §3.4.3.1/1:

If the nested-name-specifier of a qualified-id nominates a class, the name specified after the nested-namespecifier is looked up in the scope of the class (10.2), except for the cases listed below.

[ ... §3.4.3.1/2]:

In a lookup in which the constructor is an acceptable lookup result and the nested-name-specifier nominates a class C:

— if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (Clause 9) [ ... ] the name is instead considered to name the constructor of class C.

[ ... example: ]

struct A { A(); }; 
[ ... ] 
A::A a; // error, A::A is not a type name 
struct A::A a2; // object of type A 
+0

++ 1! vẻ đẹp thực sự! –

+10

@Tats_innit: Lỗi: "++ 1": yêu cầu giá trị. :-) –

+0

lolz! lỗi :: lỗi cú pháp trên đầu ... ID-10-T :) lời giải thích tốt đẹp bruv! có một cái tốt đẹp! –