2013-07-14 28 views
5

người bạn của tôi đã cho tôi thấy đoạn code sau"sử dụng" với tên lớp cơ sở để thay đổi quyền truy cập hợp lệ?

struct A { 
    virtual void f() = 0; 
    virtual void g() = 0; 
}; 

struct AInternal : A { 
    virtual void f() { /* ... */ } 
    virtual void g() { /* ... */ } 
}; 

Ông đang sử dụng AInternal như một lớp học nội mà thực hiện hầu hết (nếu không phải tất cả A). Sau đó, ông được kế thừa từ AInternal, nhưng khi ông muốn rằng AInternal vẫn không truy cập được (vì nó là một chi tiết triển khai), ông kế thừa bảo vệ (được thực hiện theo điều khoản). Những gì ông cũng đã làm là using ing tên lớp cơ sở để làm A truy cập (nó đã được bảo vệ theo mặc định, vì AInternal được thừa kế bảo vệ quá)

struct C : protected AInternal { 
    using AInternal::A; 
}; 

Trên thực tế, điều này đã làm việc tốt (nhưng như sau chúng tôi thấy, nó vẫn giữ các chức năng thành viên private - chỉ là lớp cơ sở đã được thực hiện public), nhưng nó chỉ hoạt động trên GCC. Không thể truy cập cơ sở A. Bất kỳ ý tưởng? Chúng tôi thậm chí có thể làm cho nó để phá vỡ mã hoạt động trên Clang

struct C : public AInternal { 
protected: 
    using AInternal::A; 
}; 

C *c = 0; 
A *a = c; // error on GCC! 

Ai đó có thể giúp đỡ xin vui lòng?

+0

Nếu tôi hiểu đúng thì A xác định Giao diện sẽ được cung cấp bởi C. Điều tôi thực sự không nhận được là ý tưởng đằng sau toàn bộ quá trình thiết lập. Nó làm cho các phương thức công khai trong 'AInternal' không thể truy cập nếu không có trong 'A' nhưng người ta chỉ có thể có các phương thức riêng như vậy trong' AInternal' và kế thừa công khai trong C. – Pixelchemist

+0

@Pixelchemist ý tưởng là làm cho 'sử dụng AInternal :: A' làm cho các thành viên lại hoạt động công khai. Điều đó không có tác dụng, nhưng những gì nó đã làm là làm cho lớp cơ sở 'A' có thể truy cập được. –

+0

Vâng, nhưng tôi không hiểu lý do cho loại bố cục này. Tại sao không có phương thức giao diện công khai trong 'AInternal', sử dụng thừa kế công khai và được sử dụng tốt? "Chi tiết triển khai" như chức năng trợ giúp hoặc các thành viên khác vẫn có thể được giữ riêng tư trong 'AInternal'. – Pixelchemist

Trả lời

5

Bạn chỉ ảnh hưởng đến khả năng hiển thị của tên lớp được tiêm. Việc bảo vệ truy cập của subobject cơ sở hoặc các thành viên của nó không bị ảnh hưởng. Nếu Clang hoặc GCC cho phép nó ảnh hưởng đến hiệu lực truyền hoặc truy cập trong cơ sở, đó là lỗi của chúng.

[class.member.lookup] 10,2/3 nói

Trong bộ tuyên bố, sử dụng-khai được thay thế bởi các thành viên họ chỉ định, và tờ khai loại (bao gồm cả tiêm-đẳng cấp tên) được thay thế theo các loại họ chỉ định.

Lớp phụ cơ sở không có tên trong tra cứu thành viên; tên lớp được tiêm.

+0

Vâng, nói về ma quỷ. Tôi chỉ cần nhấn một trường hợp trong mã của riêng tôi, nơi tôi giả định không chính xác rằng một tên kiểu tiêm có cùng trình độ truy cập giống như lớp cơ sở đã giới thiệu nó. Hóa ra rằng nếu bạn thực sự phụ thuộc vào nó, nó tốt hơn để xác định rõ ràng tên muối của riêng bạn, hoặc sử dụng các thành phần đặc điểm. – Potatoswatter

+0

Cảm ơn! Tôi không có ý tưởng về tất cả những điều đó và bắt đầu có giấc ngủ xấu vì tầm nhìn của lớp cơ sở. +1 –

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