2011-06-21 34 views
5
class private_object 
{ 
private: 
    struct make_public; 
    friend struct make_public; 
    static void method1() {} 
}; 

struct private_object::make_public 
{ 
    class nested_outer 
    { 
    void callFromOuter() 
    { private_object::method1(); } // Should this be an error? 

    class nested_inner 
    { 
     void callFromInner() 
     { private_object::method1(); } // How about this one? 
    }; 
    }; 
}; 

Vấn đề về tình bạn này xuất hiện khi tôi cố gắng chuyển một dự án mã nguồn mở để biên dịch dưới borland. Theo parashift và hai câu hỏi bán liên quan herehere, ví dụ trên không nên hợp lệ.Bạn bè có phải là người chuyển tiếp trong các lớp lồng nhau không?

Tuy nhiên, sau khi thử nghiệm trên bảy các trình biên dịch khác nhau , chỉ borland và dmc bị khiếu nại. Hành vi này làm tôi ngạc nhiên bởi vì tôi đã không mong đợi tình bạn để được transitive trong các lớp lồng nhau.

Vì vậy, đây đặt ra một vài câu hỏi:

  • hành vi đúng đắn là gì? Tôi đoán nó là một trong những chấp nhận bởi hầu hết các trình biên dịch.
  • Nếu đây là hành vi đúng, lý do tại sao trường hợp này là tình trạng chuyển tiếp tình bạn ok?
  • Nếu điều này đúng thì điều đó cũng ngụ ý sự thay đổi trong tiêu chuẩn. Điều gì có thể là lý do cho phép điều này trong tiêu chuẩn?
  • Đối với các trình biên dịch đã từ chối mã này, điều gì sẽ là giải pháp thích hợp? Hãy nhớ rằng một dự án thực tế có thể chứa khá sâu làm tổ nên tôi đang tìm một giải pháp có khả năng bán mở rộng.

1. thử nghiệm trên mingw-gcc 4.5.2, kêu vang, borland C++ builder2007, mars kỹ thuật số, watcom mở, visualc2010 và comeau trực tuyến

Trả lời

3

Trong C++ 03, lồng lớp không thể truy cậpprivateprotected thành viên bao quanh lớp theo mặc định (xem §11.8/1). Nhưng nếu bạn làm cho họ trở thành bạn của những lớp học kèm theo, thì họ có thể truy cập chúng. Nhưng một lần nữa lớp lồng nhau của lớp lồng nhau vẫn không phải là bạn của lớp bao ngoài cùng, lớp lồng trong của lớp lồng nhau không thể truy cập các thành viên riêng và được bảo vệ của lớp bao ngoài cùng; nó thậm chí không thể truy cập thành viên riêng tư và được bảo vệ của lớp bao quanh ngay lập tức, như đã nói ở trên. Những gì bạn đang làm là, do đó không được phép.

C++ Standard (2003) cho biết trong $ 11,8/1 [class.access.nest],

Các thành viên của một lớp lồng nhau không có tiếp cận đặc biệt cho các thành viên của một lớp kèm theo, cũng như các lớp học hoặc các hàm đã cấp 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 (khoản 11) sẽ là tuân theo.Các thành viên của lớp học kèm theo không có quyền truy cập đặc biệt vào 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 (khoản 11) sẽ là tuân theo.

Ví dụ từ Standard bản thân:

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 
    } 
}; 

của một khiếm khuyết trong C++ 03 Standard.

Nhân tiện, một lỗi lỗi trong tiêu chuẩn C++ 03. Kể từ khi lớp lồng nhau là thành viên, cần có quyền truy cập cho các thành viên tư nhân và được bảo vệ, giống như bất kỳ thành viên khác:

§9.2/1 (C++ 03):

thành viên của một lớp là các thành viên dữ liệu, chức năng thành viên (9,3), loại lồng nhau ... loại nested là lớp (9.1, 9.7) và enumerations (7.2) được định nghĩa trong lớp ...

Xem này Defect báo cáo:

1

tôi bằng cách nào đó cảm thấy rằng điều này nên được phép. Mặc dù tôi không chắc chắn về hành vi tiêu chuẩn. Ai đó có thể chỉ ra.

Đối với các trình biên dịch đã từ chối mã này, giải pháp nào thích hợp ?

tốt nhất tôi có thể nghĩ đến là làm cho một wrapper:

struct private_object::make_public 
{ 
    static void wrap_method1() { private_object::method1(); } 
    // use wrap_method1() everywhere else 
    // ... 
}; 
Các vấn đề liên quan