Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.64
Nishen
310 / 160 / 56
Регистрация: 26.02.2015
Сообщений: 798
#1

Пишем свой класс, спецификатор доступа protected - C++

09.07.2015, 18:43. Просмотров 1563. Ответов 61
Метки нет (Все метки)

Всем привет!
Из книги Р. Лафоре относительно спецификатора доступа protected:
Таким образом, если вы пишете класс, который впоследствии будет использоваться как базовый класс при наследовании, то данные, к которым нужно будет иметь доступ, следует объявлять как protected.
Далее пишется следующее:
Существуют и недостатки использования спецификатора доступа protected... это делает члены, объявленные как protected, значительно менее защищенными, чем объявленные как private.
Возникает вопросы: так когда же стоит использовать protected? Как я могу знать, захочет ли кто-нибудь использовать мой класс, как базовый? И как не доиграться со спецификаторами доступа? Как быть, если я хочу использовать чужой класс, но поля класса закрыты спецификатором private?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.07.2015, 18:43     Пишем свой класс, спецификатор доступа protected
Посмотрите здесь:
Пишем свой чекер C++
C++ пишем свой троян с нуля
C++ Пишем свой интерпретатор языка BASIC
Спецификатор доступа и виртуальные функции C++
C++ Ключ доступа protected
protected или не protected : ) C++
C++ базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит!
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ouroboros-SK
60 / 60 / 21
Регистрация: 08.09.2013
Сообщений: 187
Записей в блоге: 1
09.07.2015, 18:51     Пишем свой класс, спецификатор доступа protected #2
В хороших классах предоставляется доступ к private, через методы get и set.

Добавлено через 2 минуты
т.е
C++
1
2
3
4
5
6
7
8
class A
{
public:
  type getB();
  void setB(B);
private:
  type B;
};
Добавлено через 1 минуту
А protected чаще всего лепят в абстрактных классах или в классах, которые могут быть расширены.
Как правило, при проектировании понятно, какие классы будут расширятся, а какие нет.
Avazart
7101 / 5278 / 267
Регистрация: 10.12.2010
Сообщений: 23,274
Записей в блоге: 17
09.07.2015, 19:25     Пишем свой класс, спецификатор доступа protected #3
Цитата Сообщение от Ouroboros-SK Посмотреть сообщение
А protected чаще всего лепят в абстрактных классах или в классах, которые могут быть расширены.
В protected обычно помещают методы, а не члены класса.

Члены класса делают private как правило.
Если же вы видите класс в котором члены класса открыты то этот класс либо какой-то особенный(например не предназначенный для наследования) либо он просто так криво написан.

Добавлено через 5 минут
Цитата Сообщение от Nishen Посмотреть сообщение
Как быть, если я хочу использовать чужой класс, но поля класса закрыты спецификатором private?
Использовать доступ через предусмотренные для этого методы.
hoggy
6368 / 2586 / 451
Регистрация: 15.11.2014
Сообщений: 5,717
Завершенные тесты: 1
09.07.2015, 20:48     Пишем свой класс, спецификатор доступа protected #4
Цитата Сообщение от Nishen Посмотреть сообщение
Возникает вопросы: так когда же стоит использовать protected?
в эту секцию помещается функционал,
который должен быть доступен наследникам класса.

Цитата Сообщение от Nishen Посмотреть сообщение
Как я могу знать, захочет ли кто-нибудь использовать мой класс, как базовый?
об этом думают на этапе проектирования:
зачем вообще нужен этот базовый класс?
Mr.X
Эксперт С++
3042 / 1687 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
09.07.2015, 20:59     Пишем свой класс, спецификатор доступа protected #5
Цитата Сообщение от Nishen Посмотреть сообщение
Таким образом, если вы пишете класс, который впоследствии будет использоваться как базовый класс при наследовании, то данные, к которым нужно будет иметь доступ, следует объявлять как protected.
Еще одна глупость этого Лафоре. Сколько уже его ляпов цитировали здесь на форуме. Поражает непонятная популярность этого шарлатана. Охота же людям замусоривать себе мозги.
xEmpire
23 / 23 / 9
Регистрация: 07.12.2012
Сообщений: 169
Завершенные тесты: 1
09.07.2015, 21:03     Пишем свой класс, спецификатор доступа protected #6
Avazart, Чем плох вариант использовать данные с областью видимости protected и переопределять область видимости на private (используя using) в наследуемом классе?
Avazart
7101 / 5278 / 267
Регистрация: 10.12.2010
Сообщений: 23,274
Записей в блоге: 17
09.07.2015, 21:04     Пишем свой класс, спецификатор доступа protected #7
xEmpire, Пример кода?
hoggy
6368 / 2586 / 451
Регистрация: 15.11.2014
Сообщений: 5,717
Завершенные тесты: 1
09.07.2015, 21:05     Пишем свой класс, спецификатор доступа protected #8
Цитата Сообщение от xEmpire Посмотреть сообщение
Чем плох вариант использовать данные с областью видимости protected и переопределять область видимости на private в наследуемом классе?
очевидно тем, что они не приватные в базовом классе.
и следовательно, код обладает всеми недостатками такого рода проектирования.
xEmpire
23 / 23 / 9
Регистрация: 07.12.2012
Сообщений: 169
Завершенные тесты: 1
09.07.2015, 21:14     Пишем свой класс, спецификатор доступа protected #9
Avazart, да хоть
C++
1
2
3
4
5
6
7
8
9
class Foo {
    protected:
        int _x;
};
 
class Bar : public Foo {
    private:
        using Foo::_x;
};
Добавлено через 5 минут
hoggy, ну а если это абстрактный класс, и цели делать его интерфейсом (Pure Abstract Class) нет?
hoggy
6368 / 2586 / 451
Регистрация: 15.11.2014
Сообщений: 5,717
Завершенные тесты: 1
09.07.2015, 21:16     Пишем свой класс, спецификатор доступа protected #10
Цитата Сообщение от xEmpire Посмотреть сообщение
ну а если это абстрактный класс, и цели делать его интерфейсом (Pure Abstract Class) нет?
какая разница?

вы понимаете вообще,
откуда пошла такая манера делать все данные-члены классов приватными?

во многих книгах пишут:
по хорошему все данные-члены класса должны быть приватными.

вот зачем это нужно?
Avazart
7101 / 5278 / 267
Регистрация: 10.12.2010
Сообщений: 23,274
Записей в блоге: 17
09.07.2015, 21:16     Пишем свой класс, спецификатор доступа protected #11
Ок, зачем тогда вообще объявлять _x в классе Foo ?
Mr.X
Эксперт С++
3042 / 1687 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
09.07.2015, 21:17     Пишем свой класс, спецификатор доступа protected #12
Цитата Сообщение от xEmpire Посмотреть сообщение
чем плох вариант использовать данные с областью видимости protected
Основной принцип ООП - это минимизация зависимостей. Если в базовом классе данные protected, то классы-наследники будут зависеть от реализации базового класса, что нарушает этот принцип.
Ну и согласно принципу инкапсуляции класс должен сам управлять своими данными, а тут ими будет управлять еще кто-то, т.е. инкапсуляция нарушается. В общем, все это сильно противоречит принципам ООП.
Avazart
7101 / 5278 / 267
Регистрация: 10.12.2010
Сообщений: 23,274
Записей в блоге: 17
09.07.2015, 21:20     Пишем свой класс, спецификатор доступа protected #13
Цитата Сообщение от xEmpire Посмотреть сообщение
ну а если это абстрактный класс, и цели делать его интерфейсом (Pure Abstract Class) нет?
Ок а что дает вообще абстрактность и полиморфизм?
Одинаковый "внешний" вид/интерфейс, но возможно разное поведение (от класса к классу)
_x и вообще член класса в данном случае дает возможность варьировать поведением?
Ведь нет виртуальных членов данных? есть виртуальные методы.
xEmpire
23 / 23 / 9
Регистрация: 07.12.2012
Сообщений: 169
Завершенные тесты: 1
09.07.2015, 21:21     Пишем свой класс, спецификатор доступа protected #14
Avazart, ну например у нас есть абстрактный класс, в котором помимо чистых виртуальных методах есть метод, который выполняется в наследуемых классах одинаково, следовательно проще определить переменные здесь, и реализовать данный метод здесь используя данные переменные, а в наследуемых классах переопределить уровень доступа на закрытый.
hoggy
6368 / 2586 / 451
Регистрация: 15.11.2014
Сообщений: 5,717
Завершенные тесты: 1
09.07.2015, 21:24     Пишем свой класс, спецификатор доступа protected #15
Цитата Сообщение от xEmpire Посмотреть сообщение
есть метод, который выполняется в наследуемых классах одинаково, следовательно проще определить переменные здесь, и реализовать данный метод здесь используя данные переменные, а в наследуемых классах переопределить уровень доступа на закрытый.
это нормально - иметь не виртуальную функцию-член.
которая для всех работает одинаково.

только причем здесь данные-члены?
Avazart
7101 / 5278 / 267
Регистрация: 10.12.2010
Сообщений: 23,274
Записей в блоге: 17
09.07.2015, 21:31     Пишем свой класс, спецификатор доступа protected #16
xEmpire, Не уловил мысли.

Что к примеру будет если мы захотим изменить "базовое" поведение ? И вместо x нам нужно будет считать x1+x2 ?

C++
1
2
3
4
5
class Foo 
{
    protected:
        int _x;
};
И

C++
1
2
3
4
5
6
7
class Foo
 {
    private:
          int x_;    
    protected:
         int x()const{ return x_; }
};

C++
1
2
3
4
5
6
7
8
9
10
class Foo
{
    private:
          int x1_,x2_;    
    protected:
         int x()const
         { 
             return x1_+x2_; // Изменение которое допустим потребуется в будущем.
         } 
};
Интерфейс не изменился, а поведение изменилось, но наследники это "не ощутят" в плане в них изменять ничего не придется если они использую метод, а не член класса.
xEmpire
23 / 23 / 9
Регистрация: 07.12.2012
Сообщений: 169
Завершенные тесты: 1
09.07.2015, 22:54     Пишем свой класс, спецификатор доступа protected #17
Цитата Сообщение от hoggy Посмотреть сообщение
это нормально - иметь не виртуальную функцию-член.
которая для всех работает одинаково.

только причем здесь данные-члены?
Ну если у нас есть абстрактный класс, следовательно создать экземпляр этого класса не возможно.
Если в нашем классе есть методы, которые должны быть для наследников реализованы по разному, они объявленные как чистые виртуальные методы, иначе это просто методы.
Если чистый виртуальный метод должен быть реализацией (в наследуемом классе у перекрытого метода будет изменена область видимости на protected | private), а не интерфейсом в наследуемом классе, то он должен быть объявлен с областью видимости protected иначе, если использовать этот метод виртуальным вызовом, то вызов этого метода будет разрешен, независимо, какая область видимости этого метода в наследнике.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
class Foo {
public:
    virtual void Test() const = 0 ;    
};
 
class Bar : public Foo {
    void Test() const override
    {
         std::cout << "test";
    }
};
 
int main() {
    Foo *p = new Bar();
    p->Test(); // вызов функции будет разрешен
}
При расширении этого класса (наследуем интерфейс), переопределяя виртуальные методы при их реализации обращаясь к данным-членам суперкласса, зачем нам использовать get и set методы, если хочется работать напрямую? Почему не сделать в суперклассе данных защищенным, а в наследуемом сделать их закрытыми и при расширении работать с данными напрямую, а при работе извне -используя set и get методы?
Avazart
7101 / 5278 / 267
Регистрация: 10.12.2010
Сообщений: 23,274
Записей в блоге: 17
09.07.2015, 23:04     Пишем свой класс, спецификатор доступа protected #18
Цитата Сообщение от xEmpire Посмотреть сообщение
если хочется работать напрямую?
Когда хочется, бьем по кривым рукам что бы не хотелось лезть туда куда не стоит.

Добавлено через 2 минуты
Цитата Сообщение от xEmpire Посмотреть сообщение
очему не сделать в суперклассе данных защищенным, а в наследуемом сделать их закрытыми и при расширении работать с данными напрямую, а при работе извне -используя set и get методы?
Вы предлагаете самого старта нарушить инкапсуляцию, а потом героически попытаться это дело исправить?
xEmpire
23 / 23 / 9
Регистрация: 07.12.2012
Сообщений: 169
Завершенные тесты: 1
09.07.2015, 23:13     Пишем свой класс, спецификатор доступа protected #19
Avazart, Не знаю по чему, но при чтении топика, мне почему-то показалось, что при public наследовании, protected становится public, а тут такие дела
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.07.2015, 23:51     Пишем свой класс, спецификатор доступа protected
Еще ссылки по теме:
Свой класс в С++ C++
C++ Создать свой класс
C++ Свой контейнерный класс
Свой класс string C++
Строки свой класс C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
hoggy
6368 / 2586 / 451
Регистрация: 15.11.2014
Сообщений: 5,717
Завершенные тесты: 1
09.07.2015, 23:51     Пишем свой класс, спецификатор доступа protected #20
Цитата Сообщение от xEmpire Посмотреть сообщение
При расширении этого класса (наследуем интерфейс), переопределяя виртуальные методы при их реализации обращаясь к данным-членам суперкласса, зачем нам использовать get и set методы, если хочется работать напрямую?
наряду с понятием "инкапсуляция" есть ещё понятие "инвариант".

суть инкапсуляции:
возможность использовать функционал без необходимости знать детали внутренней реализации.
(нам не нужно знать какие есть данные-члены у суперкласса, что бы дергать его методы)


суть инварианта:
компонент гарантирует стабильность своей работы (отсутствие крашей, утечек ресурсов и тп),
независимо от корректности вызывающей стороны.

то есть, даже если вызывающая сторона запускает функцию с плохими аргументами,
инвариантный компонент это пофиксит, и обработает ошибку.
и никаких сбоев в его работе не будет.


но если бы данные-члены были открытыми,
тогда любой желающий мог бы залезть,
и как то их подкрутить.

и такой компонент вам уже ничего гарантировать не сможет.

архитектура, которая состоит из компонентов,
которые никому ничего не гарантирует - подвережна многочисленным ошибкам.
плохо расширяется. хрупкая (плохо переносит изменения), и тп.
Yandex
Объявления
09.07.2015, 23:51     Пишем свой класс, спецификатор доступа protected
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru