Почему я могу получить доступ к этому приватному члену из другого объекта? - PullRequest
2 голосов
/ 01 мая 2020

В настоящее время я изучаю C ++ из Страуструпа «Программирование: принципы и практика», и есть пример, который я не могу понять. Существует класс, который называется Link и выглядит следующим образом.

class Link{

public:

    Link(Link* p=nullptr, Link* n=nullptr, const std::string& label);
    Link* erase();

private:
    std::string label;
    Link* succ;
    Link* prev;

};


Link* Link::erase() {

    if (this ==  nullptr) return nullptr;

    if(prev) prev->succ = succ;
    if(succ) succ->prev = prev;

    return succ;


}

Что я не понимаю, так это то, почему prev->succ = succ; является правильным, поскольку я присваиваю закрытый член объекта из другого объекта. Что мне здесь не хватает?

Ответы [ 4 ]

2 голосов
/ 01 мая 2020

Доступ для класса, а не для объекта. Многие вещи не будут работать как они, если доступ будет для каждого экземпляра. Например, этот тип

class foo {
    int x;
};

имеет конструктор копирования, сгенерированный компилятором, который выглядит примерно так:

foo::foo(const foo& other) {
    x = other.x;
}

Ограничения доступа предназначены для инкапсуляции, а инкапсуляция должна гарантировать, что инварианты класса не нарушено. Однако, как правило, инваранты временно нарушаются внутри методов. Например, рассмотрим этот класс

class Sum {
    int a = 0;
    int b = 0;
    int sum = 0;
public:
    void set(int x,int y);
    int get_sum() { return sum; }
};

Инвариант здесь заключается в том, что sum всегда является суммой a и b. Однако внутри метода set ...

void Sum::set(int x,int y) {
    a = x;
    b = y;
    sum = a + b;
}

Этот инвариант восстанавливается только в самой последней строке. Вы несете ответственность за восстановление инварианта таким образом, чтобы он всегда имел внешний вид.

Кроме того, ограничение доступа состоит в том, чтобы скрыть детали реализации. В примере Sum пользователь не знает, что элемент sum существует, и ему не нужно знать об этом. Однако определение методов класса связано с деталями реализации. Работа с деталями реализации другого объекта не имеет значения, потому что они одинаковы.

Какое отношение к вашему примеру?

Цель ограничений доступа - дать вам возможность убедиться, что инварианты извне никогда не нарушены, и скрыть детали реализации. Внутри метода Link вы должны знать, что вы делаете. Вы должны знать, что означают prev и succ, являются ли они членами this или другого объекта. Метод должен убедиться, что инварианты не нарушены: после вызова erase у вызывающего абонента остается действительный Link. И для этого вы имеете дело с деталями реализации: действительный Link имеет prec и succ.

Заключение: Неспособность получить доступ к закрытым методам других объектов была бы серьезным препятствием и на самом деле не приносила бы пользы (поскольку в любом случае, находясь внутри метода, вы уже имеете дело с деталями реализации класса и часто делаете временно нарушать инварианты).

1 голос
/ 01 мая 2020

Ограничения доступа применяются к именам , а не объектам.

С [class.access]:

Член класса может быть

  • личным; то есть его имя может использоваться только членами и друзьями класса, в котором оно объявлено.

  • protected; то есть его имя может использоваться только членами и друзьями класса, в котором он объявлен, классами, производными от этого класса, и их друзьями (см. [class.protected]).

  • публично; то есть его имя может использоваться где угодно без ограничения доступа.

(выделение добавлено)

0 голосов
/ 01 мая 2020

Вы можете задать себе вопрос, как работают конструкторы копирования.

инкапсуляция для классов, а не объектов.

инкапсуляция - это способ "скрыть" код за пределами класса , В классе доступны все частные поля и функции. Это не способ защиты объектов, это способ скрыть реализации, которые пользователям класса не нужны, чтобы улучшить эффективность разработки.

0 голосов
/ 01 мая 2020

Поскольку частные члены являются частными для класса , не только экземпляр .

Таким образом все экземпляры Link могут видеть личные члены друг друга, а не только их собственные.

...