2010-08-21 52 views
16

Mã này biên dịch trên msvc/g ++:lớp lồng nhau: Truy cập vào protected member của lớp bao quanh lớp từ một lớp bảo vệ lồng nhau

class A{ 
protected: 
    int i; 
    class B{ 
    public: 
     A* a; 
     B(A* a_) 
     :a(a_){ 
     } 
     void doSomething(){ 
      if (a) 
       a->i = 0;//<---- this part 
     }  
    }; 
public: 
    A() 
    :i(0){ 
    } 
}; 

Như bạn thấy, B được quyền truy cập vào phần "bảo vệ" của bao quanh lớp, mặc dù nó không được khai báo là bạn.

Đây có phải là hành vi tiêu chuẩn (tuân thủ tiêu chuẩn) không?

Tôi thỉnh thoảng sử dụng tính năng này, nhưng tôi không nhớ quy tắc nói rằng lớp được bảo vệ lồng nhau sẽ tự động nhận được quyền truy cập vào tất cả dữ liệu được bảo vệ của lớp bao quanh.

+0

Câu hỏi về câu hỏi. Tôi sẽ không tìm kiếm bản gốc ngay bây giờ. :) –

Trả lời

13

Trong tiêu chuẩn C++ 03, 11.8p1 nói:

Các thành viên của một lớp lồng nhau không có quyền truy cập đặc biệt cho các thành viên của một lớp kèm theo.

Tuy nhiên, độ phân giải cho defect report 45 (với tiêu chuẩn) khẳng định điều ngược lại, và do đó định nghĩa hoạt động bạn đã xem:

Một lớp lồng nhau là thành viên và như vậy có khả năng tiếp cận tương tự quyền như bất kỳ thành viên nào khác.

Trong C++ 0x văn bản của 11.8 đã được thay đổi để phản ánh thực tế này, vì vậy đây là hành vi hợp lệ cho cả trình biên dịch phù hợp C++ 03 và C++ 0x.

Xem thêm this thread từ diễn đàn cprogramming.com.

+2

+1 Câu trả lời hay. Tuy nhiên, nếu bạn google này, có một số tài liệu trình biên dịch XL của IBM chỉ đề cập đến phần đầu tiên bạn đã nói và ngụ ý rằng mã OP sẽ không biên dịch. Vì vậy, điều di động để làm hiện nay, cho đến khi C++ 0x được triển khai rộng rãi, sẽ là khai báo lớp lồng nhau như một người bạn trong lớp kèm theo. – Praetorian

+0

Tìm tốt. Một liên kết sẽ là tốt đẹp vì lợi ích của sự hoàn chỉnh. :) –

+0

Tôi đã được lười biếng trước đó :-), đây là liên kết. http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp?topic=/com.ibm.xlcpp101.aix.doc/language_ref/cplr061.html – Praetorian

0

Tham khảo $ 9,7/1. Ngoại trừ bằng cách sử dụng con trỏ rõ ràng, tài liệu tham khảo, và tên đối tượng, khai báo trong một lớp lồng nhau chỉ có thể sử dụng tên loại, thành viên tĩnh, và điều tra từ lớp kèm theo. . "

5

Tôi không có một bản sao của C++ 03 tiện dụng nhưng từ một dự thảo (n3090) của C++ 0x:

11,8 lớp lồng nhau

Một lồng nhau lớp là thành viên và do đó có cùng quyền truy cập như bất kỳ thành viên nào khác. Các thành viên của một lớp học kèm theo không có quyền truy cập đặc biệt đối với các thành viên của lớp học lồng nhau ; các quy tắc truy cập thông thường (Khoản 11) sẽ được tuân theo.

[Ví dụ:

class E { 
    int x; 
    class B { }; 
    class I { 
     B b; // OK: E::I can access E::B 
     int y; 
     void f(E* p, int i) { 
      p->x = i; // OK: E::I can access E::x 
     } 
    }; 
    int g(I* p) { 
     return p->y; // error: I::y is private 
    } 
}; 

Vì vậy, ít nhất là trong các tiêu chuẩn tiếp theo, các lớp học kèm theo có thể truy cập các thành viên lớp bên ngoài như bất kỳ chức năng thành viên bình thường nào.

Cập nhật: Điều này không được phép trong tiêu chuẩn hiện tại. Nhưng một báo cáo lỗi (DR 45) đã được đệ trình để sửa lỗi này.(chỉnh sửa SIGTERM của mất một này ra Xin vui lòng, hãy cẩn thận..)

Cập nhật # 2: Tôi đã thử với VS2010, g ++ (4.0.1 Apple) với -Wall -ansi -pedantic -std=c++98 và Comeau (4.3.10.1) trong nghiêm ngặt C + Chế độ +03 với phần mở rộng C++ 0x bị vô hiệu hóa - tất cả chúng dường như chấp nhận quyền truy cập vào các thành viên lớp bên ngoài private trong các thành viên lớp bên trong.

0

Đây có phải là hành vi tiêu chuẩn (tuân thủ tiêu chuẩn) không?

Không.

Theo C++ - 2003

Section 11.8.1

lớp lồng nhau

Các thành viên của một lớp lồng nhau không có quyền truy cập đặc biệt cho các thành viên của một lớp kèm theo, cũng không phải đến các lớp học hoặc các chức năng đã trao tình bạn cho một lớp học kèm theo; các quy tắc truy cập thông thường (điều 11) sẽ được tuân theo. Các thành viên của một lớp kèm theo không có quyền truy cập đặc biệt vào các thành viên của một lớp lồng nhau; các quy tắc truy cập thông thường (điều 11) sẽ được tuân theo.

[Example: 
class E { 

    int x; 
    class B { }; 
    class I { 

     B b; //error: E::B is private 
     int y; 
     void f(E* p, int i) 
     { 
      p->x = i;   //error: E::x is private 
     } 
    }; 
    int g(I* p) 
    { 
      return p->y; //error: I::y is private 
    } 
}; 
—end example] 

Nhưng có một sửa đổi nhỏ đến phần đó trong ISO/IEC N 3092 mà nói

Một lớp lồng nhau là thành viên và như vậy có quyền truy cập giống như bất kỳ thành viên khác. Các thành viên của một lớp kèm theo không có quyền truy cập đặc biệt vào các thành viên của một lớp lồng nhau; các quy tắc truy cập thông thường (Điều 11) sẽ được tuân theo.

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