2015-10-18 14 views
5

Hãy giúp tôi hiểu tại sao có thể cho hàm thành viên của lớp trả về một đối tượng lớp lồng nhau riêng và tại sao nó có thể gọi hàm thành viên trên lớp lồng nhau riêng đó, ví dụ :Truy cập vào lớp lồng nhau được trả về từ hàm thành viên

class Y 
{ 
    class X 
    { 
    public: 
     void f() { cout << "Hello World" << endl; } 
    }; 

public: 
    X g() { return X(); } 
}; 

void h() 
{ 
    Y::X x;  // Error, as expected: class Y::X is private. 
    x.f();  // Error. 

    Y y;  // OK. 
    y.g().f(); // OK. But why??? 
} 

Tôi đã thử nghiệm với GCC và Visual C++ và dòng cuối cùng biên dịch trên cả hai. Tôi dường như không thể tìm thấy bất cứ điều gì trong tiêu chuẩn C++ mà sẽ làm cho điều này hợp lệ. Bất kỳ ý tưởng tại sao điều này hoạt động?

Edit:

Một quan sát:

void i() 
{ 
    Y y; 

    Y::X x2 = y.g(); // Error: class Y::X is private 
    x2.f();   // Error 

    auto x3 = y.g(); // OK 
    x3.f();   // OK 
} 
+4

Cả hai chức năng đều là 'công khai' và bạn thực sự không sử dụng 'X' ở bất kỳ đâu. –

+0

Định nghĩa 'X' là riêng tư, nhưng hàm' g() 'là công khai. Vì vậy, không có vấn đề gì cả. – Chiel

Trả lời

5

Tạo lớp lồng nhau private không có nghĩa là phạm vi bên ngoài không bao giờ có thể sử dụng một phiên bản của lớp đó. Trình chỉ định truy cập ảnh hưởng đến tên và chức năng main của bạn không bao giờ cố gắng để tênY::X. Nơi duy nhất trong đó Y::X được đặt tên trong phạm vi Y, tất nhiên là có quyền truy cập vào các thành viên private riêng của mình. Hàm trả về một thể hiện của Y::X đến main không có liên quan đặc biệt.

[C++14: 11/1]: Một thành viên của một lớp có thể

  • private; nghĩa là, chỉ có thể sử dụng tên tên của các thành viên và bạn bè của lớp học được khai báo.
  • protected; có nghĩa là, tên của nó chỉ có thể được sử dụng bởi các thành viên và bạn bè của lớp mà nó được khai báo, bởi các lớp bắt nguồn từ lớp đó, và bởi bạn bè của họ (xem 11.4).
  • public; nghĩa là tên của nó có thể được sử dụng ở mọi nơi mà không bị giới hạn truy cập.

Phải thừa nhận rằng, tiêu chuẩn không có bất kỳ văn bản để rõ ràng unconfuse bạn và chỉ ra rằng tiếp cận với các đối tượng bản thân không được điều khiển bởi các từ khóa này, nhưng điều đó chắc chắn là mục đích và cuối cùng, như xa như pháp lý đi.

Tên đó là Y::X::f, nhưng tên đó là public.

+0

Bây giờ tôi tò mò: liệu có thể lưu trữ kết quả của 'g()' trong một biến trước khi giới thiệu 'tự động'? –

+0

@SvenMarnach: Tôi không thấy như thế nào. –

+1

Thú vị. Tôi đã không nhận ra rằng 'tự động' cho phép khai báo mà nếu không thì không thể. Tôi luôn nghĩ rằng 'auto' chủ yếu là một tính năng tiện lợi. –

1

đây bạn có thể tìm thấy những ví dụ mà bạn đang tìm kiếm. f1 là công khai, f2 là tư nhân và kích hoạt lỗi bạn đang mong đợi:

#include <iostream> 

class Y 
{ 
    class X 
    { 
     public: 
      void f1() { std::cout << "Hello World" << std::endl; } 
     private: 
      void f2() { std::cout << "Hello World" << std::endl; } 
    }; 

    public: 
     X g() { return X(); } 
}; 

int main() 
{ 
    // Y::X x;  // Error, as expected: class Y::X is private. 
    // x.f();  // Error. 

    Y y;   // OK. 
    y.g().f1(); // OK. Because f1 is public. 
    y.g().f2(); // Error. Because f2 is private. 

    return 0; 
} 
+0

Tôi nghĩ rằng OP đã tự hỏi tại sao 'yg()' làm việc, nhiều như bất cứ điều gì ... đặc biệt khi họ đi ra khỏi con đường của họ để cho thấy rằng chúng ta có thể thực sự thể hiện một 'Y :: X' miễn là chúng ta tránh đặt tên kiểu của nó, sử dụng 'auto'. –

+0

Có thể. Trong trường hợp đó, câu trả lời của tôi có thể bị xóa. Hãy để OP quyết định. – Chiel

+0

Vâng, tất nhiên. Tôi vừa nói rồi. –

2

lý do tại sao nó có thể cho một hàm thành viên lớp để trả về một đối tượng lớp lồng nhau tin

Một lớp lồng nhau là một thành viên lớp học, và chức năng thành viên có quyền truy cập ngay trên thành viên riêng.

và tại sao nó là sau đó có thể gọi hàm thành viên trên đó lớp lồng nhau tin

Bạn không sử dụng tên lớp lồng nhau tin ở đây, ví dụ: Y::X. Và Y::X::f() là một chức năng công khai, do đó, có thể gọi trực tiếp.

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