2012-01-01 12 views
7

Tôi nghĩ rằng tôi biết accessibilty nhưng tôi không chắc chắn nếu tôi hiểu tầm nhìn rất rõ ràngMức độ hiển thị của các thành viên Nhóm?

Ví dụ:

class X 
{ 
    int x; 
}; 

Ở đây, 'x' là chỉ hiển thị trong lớp và nhưng truy cập bên ngoài Của Lớp. Nếu tôi chính xác, Ai đó có thể giải thích văn bản trong đó câu trả lời về mức độ hiển thị không được kiểm soát, v.v.?

(C++ 03/11.0) Cần lưu ý rằng đó là quyền truy cập vào các thành viên và lớp cơ sở mà được kiểm soát chứ không phải khả năng hiển thị của chúng. Tên của các thành viên vẫn là hiển thị và chuyển đổi tiềm ẩn cho các lớp cơ sở vẫn là được xem xét khi các thành viên và lớp cơ sở không thể truy cập được. Việc giải thích của một cấu trúc cụ thể được thiết lập mà không liên quan đến điều khiển truy cập . Nếu cách diễn giải được thiết lập sử dụng tên thành viên hoặc lớp cơ sở không thể tiếp cận, thì cấu trúc là không đúng định dạng.

+0

Bạn nên yêu cầu làm rõ trong các nhận xét của câu trả lời đó. –

+1

@ TomalakGeret'kal: Tôi sẽ chỉ xóa tham chiếu đến câu trả lời đó khỏi câu hỏi của tôi. – user1086635

+1

Um .. đó là loại trái ngược với những gì tôi đề nghị là điều phải làm. –

Trả lời

7

Có lẽ ví dụ này giúp:

class Bob 
{ 
private: 
    int foo(int, int); 
}; 

class David : Bob 
{ 
    void goo() { 
     int a = foo(1, 2); // #1 
    } 
}; 

class Dani : Bob 
{ 
    void foo(); 
    void goo() { 
     int a = foo(1, 2); // #2 
    } 
}; 

On line # 1, tên foonhìn thấy, nhưng các chức năng mà nó tên là không truy cập (trên tài khoản của bị tin tới Bob). Đây là một lỗi biên dịch, nhưng trình biên dịch biết rằng có một hàm có khả năng là Bob::foo sẽ phù hợp, nhưng không thể truy cập được.

On line # 2, tên foo chỉ đề cập đến Dani::foo, trong khi Bob::fookhông nhìn thấy được (vì nó là ẩn), và do đó chỉ đơn giản là không có chức năng phù hợp cho các cuộc gọi foo(1, 2). Đây cũng là lỗi biên dịch, nhưng lần này lỗi là không có hàm nào phù hợp cho cuộc gọi.

+1

Tôi có thể biết nó có thể gây ra sự nhầm lẫn nào không? – user1086635

+0

@ user1086635 không chắc chắn ý của bạn ở đây: Các số dòng đơn giản không khớp với mô tả. Dòng # 1 là "Class Bob" nhưng anh ta có nghĩa là "int foo (int, int);" và Dòng # 2 là "{". Từ ngữ cần chỉnh sửa. – Serodis

+0

@Serodis: Các tham chiếu đến các dòng được đánh dấu bằng các chú thích '// # 1' vv. Kiểu chú thích này là thông lệ phổ biến ở đây trên SO, vì các khối nguồn không có bất kỳ dạng thức đánh số dễ thấy nào khác. –

7

C++ có một số tính năng bí truyền liên quan đến khả năng hiển thị và khả năng truy cập tên thành viên của lớp riêng tư. Theo định nghĩa, tên thành viên lớp riêng tư chỉ có thể truy cập được bởi các thành viên và bạn bè của lớp. Tuy nhiên, quy tắc hiển thị có thể gây nhầm lẫn nhiều. Chúng có thể được tóm tắt như sau.

  1. Tên thành viên riêng chỉ có thể truy cập được cho các thành viên và bạn bè khác.
  2. Thành viên riêng tư hiển thị với tất cả các mã xem định nghĩa của lớp học. Điều này có nghĩa là các loại tham số của nó phải được khai báo ngay cả khi chúng không bao giờ cần thiết trong đơn vị dịch này ...
  3. Độ phân giải quá tải xảy ra trước khi kiểm tra khả năng truy cập.

Trong C++ ngày hôm nay ("C++ 03" và các biến thể trước đó), các khái niệm về khả năng tiếp cận và tầm nhìn là độc lập. Các thành viên của các lớp và các không gian tên có thể nhìn thấy bất cứ khi nào chúng được "trong phạm vi " và không có cơ chế để giảm tầm nhìn này từ điểm khai báo. Trợ năng chỉ là thông số cho các thành viên của lớp và trực giao với khái niệm về mức độ hiển thị .Quan sát thứ hai này thường gây ngạc nhiên cho người lập trình C++ mới làm quen. Xem trang này PDF.

Hãy xem ví dụ sau.

#include < complex> 

class Calc 
{ 
    public: 
     double Twice(double d); 
    private: 
     int Twice(int i); 
     std::complex Twice(std::complex c); 
}; 

int main() 
{ 
    Calc c; 
    return c.Twice(21); // error, Twice is inaccessible 
}  

Khi trình biên dịch có để giải quyết các cuộc gọi đến một chức năng, nó làm ba điều chính, theo thứ tự:

  • Trước khi làm bất cứ điều gì khác, tìm kiếm biên dịch cho một phạm vi mà có ít ít nhất một thực thể có tên là Twice và lập danh sách các ứng cử viên. Trong trường hợp này, tra cứu tên đầu tiên nhìn vào phạm vi của Calc để xem nếu có ít nhất một hàm có tên là Hai lần; nếu không có, cơ sở lớp học và không gian tên kèm theo sẽ được xem xét lần lượt, một tại thời điểm , cho đến khi phạm vi có ít nhất một ứng cử viên được tìm thấy. Tuy nhiên, trong trường hợp này, phạm vi đầu tiên mà trình biên dịch nhìn vào đã có một thực thể có tên là Twice - trên thực tế, nó có ba trong số chúng và do đó bộ ba trở thành tập hợp các ứng cử viên. (Để biết thêm thông tin về tên tra cứu trong C++, với cuộc thảo luận về làm thế nào nó ảnh hưởng đến cách bạn nên gói lớp học của bạn và giao diện của họ

  • Tiếp theo, trình biên dịch thực hiện nghị quyết tình trạng quá tải để chọn độc đáo phù hợp nhất ra khỏi Trong trường hợp này, đối số là 21, là một int, và các tình trạng quá tải có sẵn sẽ tăng gấp đôi, một số int và phức tạp. Rõ ràng tham số int là đối sánh tốt nhất cho đối số int (đó là đối sánh chính xác và không có chuyển đổi nào là bắt buộc), và vì vậy, Twice (int) được chọn.

  • Cuối cùng, trình biên dịch thực hiện kiểm tra khả năng truy cập để xác định liệu chức năng đã chọn có thể được gọi hay không.

Lưu ý rằng khả năng tiếp cận (được định nghĩa bởi bổ ngữ trong C++) và tầm nhìn là độc lập. Khả năng hiển thị dựa trên các quy tắc phạm vi của C++. Thành viên lớp học có thể là hiển thịkhông thể truy cập được cùng một lúc.

thành viên tĩnh là một ví dụ là có thể nhìn thấy toàn cầu thông qua các hoạt động của ứng dụng của bạn nhưng truy cập chỉ liên quan đến các sửa đổi áp dụng cho chúng với.

1

Là một lưu ý: (. Trái ngược với một struct nơi các thành viên là công khai theo mặc định) khi bạn khai báo một class, phạm vi là tin theo mặc định

Biến thành viên 'x' là chỉ truy cập bằng lớp học của bạn và bạn bè của nó. Không ai khác có thể truy cập trực tiếp 'x' (nó có thể gián tiếp nếu bạn có một hàm trả về một tham chiếu đến nó, đó là một ý tưởng thực sự tồi.)

Văn bản bạn trích dẫn về khả năng hiển thị cho trình biên dịch, vì vậy X::x tồn tại, không có vấn đề gì. Nó sẽ không biến mất chỉ vì nó là riêng tư.Khả năng hiển thị được sử dụng để tìm thành viên mà bạn đang tham chiếu và kết quả phù hợp đầu tiên được trả lại. Tại thời điểm đó trình biên dịch kiểm tra khả năng truy cập, nếu có thể truy cập, bạn đều tốt. Nếu không phải là bị lỗi hình thành.

Lưu ý rằng tôi đã đề cập đến bạn bè. Từ khóa đó làm cho tất cả các thành viên có thể truy cập được. Khi trình biên dịch giao dịch với một người bạn, nó hoàn toàn bỏ qua tất cả các từ khóa được bảo vệ và riêng tư.

Trong hầu hết các trường hợp, đó là một quá trình rất dễ dàng. Nó đi theo thứ tự. Giai đoạn.

Trường hợp nó trở nên phức tạp hơn khi bạn bắt đầu sử dụng chức năng ảo: có thể được công khai, bảo vệ và riêng tư và có thể thay đổi tùy thuộc vào khai báo lớp ... (A xuất phát từ B và thực hiện chức năng ảo được bảo vệ công cộng, nó thường không phải là một ý tưởng tốt, nhưng C++ không ngăn cản bạn làm như vậy.) Tất nhiên điều này chỉ áp dụng cho các chức năng, không phải thành viên biến, vì vậy đó là một chủ đề khác nhau.