Почему я не могу получить доступ к закрытым членам внешнего класса из внутреннего класса при вложении классов? - PullRequest
0 голосов
/ 20 апреля 2020
class X
{
    int Xi;

    class Y
    {
        int Yi;

        void func()
        {
            X x;
            x.Xi = 5;
        }
    };

    void func()
    {
        Y y;
        y.Yi = 5;
    //  ^^^^ 'X::Y::Yi': cannot access private member declared in class 'X::Y'
    }
};

Я узнал о паттерне Memento, и в книге, которую я прочитал, было указано, что одним из способов достижения паттерна является написание класса Memento внутри класса Originator, чтобы только Originator может иметь доступ к закрытым членам класса Memento. Когда я попытался применить этот метод, я получил ошибку, сообщающую, что приватный член недоступен. Я знаю, что могу использовать ключевое слово friend, и это даст мне доступ к частным пользователям. Также я знаю, что могу получить доступ к закрытым членам внешнего класса из внутреннего класса. Но почему внутренний класс не может получить доступ к закрытым членам внутреннего класса?

Я могу сделать это в java, например:

public class X {

    int Xi;

    public class Y
    {
        private int Yi;

        public void func()
        {
            X x = new X();
            x.Xi = 5;
        }
    }

    public void func()
    {
        Y y = new Y();
        y.Yi = 5;
    }
}

Почему это невозможно в C ++

Ответы [ 2 ]

2 голосов
/ 20 апреля 2020

Несмотря на заголовок вашего вопроса, вы пытаетесь сделать в строке y.Yi = 5; доступ к закрытому члену внутреннего класса из тела внешний класс. Вы не можете этого сделать, потому что Yi член private - поэтому к нему можно получить доступ только из его класса.

С другой стороны, строка x.Xi = 5; действительно имеет доступ закрытый член класса внешний из класса внутренний ; это вам разрешено делать, потому что ваш внутренний Y класс является частью внешнего X класса.

Один из способов обойти это - объявить функцию X::func() другом из class Y; однако затем вам нужно будет предоставить «прототип» этой функции до того, как вы сделаете это объявление, и вам, таким образом, нужно будет сделать фактическое определение функции снаружи тело класса (оно должно идти после объявления class Y, так как оно использует объект этого класса):

class X {
private: // Even without this line, members are private by default!
    int Xi;
    void func(); // Just a declaration (prototype) - wwwe still need the definition
    class Y {
    private:
        int Yi;
        void func() {
            X x;
            x.Xi = 5;
        }
        friend void X::func();
    };
};

void X::func() { // This is the actual definition of the function.
    Y y;
    y.Yi = 5;
}
0 голосов
/ 20 апреля 2020
#include <iostream>

using namespace std;

class X
{
    public:
    int Xi;

    class Y
    {
        public:
        int Yi;

        void func()
        {
            X x;
            x.Xi = 5;
        }
    };

    void func()
    {
        Y y;
        y.Yi = 5;
    }
};

В этом коде я только что объявил ученикам c.

...