1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
|
||||||
1 | ||||||
Наследование и защищенные члены12.04.2011, 15:45. Показов 2790. Ответов 23
Метки нет (Все метки)
Добрый день всем.
У меня имеется следующий набор классов Visitor <- User <- Manager <- Admin Visitor - самый базовый, надеюсь, иерархия ясна. В каждом классе есть пара виртуальных функций, меня интересует сейчас virtual bool set(User* user, char *nm) в классе Admin. Она должна по переданным параметрам менять атрибут name для переданного юзера и придавать ему значение строки nm. Проблема в том, что я не могу обратиться к user->name, хотя вообще говоря нахожусь в теле потомка. Через User может передаваться User, Manager или Admin.
0
|
12.04.2011, 15:45 | |
Ответы с готовыми решениями:
23
Невозможно явно декларировать элементы, которые определены в пространстве имен, как частные, защищенные или защищенные внутренние Наследование и члены базового класса Наследование от protected класса: будут ли public члены класса Б доступны классу А Переставить члены последовательности так, чтобы сначала расположились все ее неотрицательные члены |
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|
12.04.2011, 16:17 | 2 |
К защищённым полям напрямую можно обращаться только из методов классов-потомков. Все остальные должны пользоваться интерфейсом класса, в котором определено защищённое поле.
0
|
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
|
|
12.04.2011, 16:25 [ТС] | 3 |
Deviaphan: Дык ведь это и есть метод класса-потомка!
Да, уточню, 117 строка у меня не работает.
0
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|
12.04.2011, 20:50 | 4 |
Это не совсем метод класса потомка.) Ты вызываешь поле из объекта дочернего класса, а не из объекта класса Admin. Т.е. ты можешь обратиться к полю name из класса Admin, но обратиться к полю name через объект класса User ты не можешь.
А вообще, ты там запланировал метод GetName, так что реализуй его и используй.) Тогда и поля можно сделать закрытыми.
0
|
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
|
|
12.04.2011, 20:58 [ТС] | 5 |
Deviaphan: А вот по поводу реализации GetName - если я это сделаю, то Getname будет свой для каждого класса.
Т.е. тогда в силу виртуальности он будет вызван для объекта этого класса и из него - т.е. надо будет, чтобы GetName объекта с недостаточным доступом - Manager или User - возвращал эту строку и ее можно было бы изменять? Не будет ли это неправильно?
0
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|
13.04.2011, 07:09 | 6 |
Правильно будет так, как тебе нужно. Механизм виртуальных функций для того и придуман, чтобы поведение изменять.
Другое дело, нужны ли тебе разные реализации? И, почему Visitor возвращает 0, хотя name определена именно в нём.
0
|
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
|
|
13.04.2011, 10:30 [ТС] | 7 |
Ну теоретически Визитор - он никто и имени своего посмотреть не может.
Также как и Юзер, хотя вот у него имя уже есть. А Менеджер может посмотреть. Ну Админ может менять имя, в том числе и у себя, и у других Админов. Но если я передаю в функцию set Админа указатель на юзера или менеджера, то в силу работы виртуальной функции, она вызовется та, что переопределена в этом самом классе - ну, на который указатель. Иначе мне придется дать слишком много привилегий Юзеру - разрешить его функции менять имя, например. Или я чего-то не понимаю?
0
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|
13.04.2011, 14:34 | 8 |
Поле name задано в классе Визитёр, соответственно и интерфейс для работы с именем можно задать в нём. Или ты собрался реализовывать метод GetName сложнее, чем просто return name?
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
||||||
13.04.2011, 16:38 | 9 | |||||
Нельзя ли поподробнее? То есть я просто хочу уточнить,
0
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|
13.04.2011, 17:05 | 10 |
Я не знаю, почему так. Честно скажу, сам был удивлён. Специально пример скомпилировать попробовал.)
Думаю, дело в том, что класс Admin и класс User - разные классы, хоть Admin и является дочерним для User. Я не знаю, что поэтому поводу сказано в стандарте.) Тут объект одного типа пытается получить доступ к защищённому полю объекта другого типа. Думаю, правильно, что нельзя. Меньше возможностей для ошибки.
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
||||||
13.04.2011, 18:12 | 11 | |||||
Ну у меня в учебнике написано по поводу protected
"Член может быть доступен из функции, только если она член класса или подкласса" То есть вроде как всё верно, не фиг через адреса объектов, которые не являются старшими родственниками, получать доступ к приватным членам. А тогда тем страннее выглядит определение set в классе User
A типа User и объект B типа User. И мы спокойно передадим объекту A адрес объекта B. А тот, в свою очередь, даст объекту A значение name. И это при всём при том, что A и B могут иметь разных отцов, то есть между ними вообще никаких родственных связей может не быть!
0
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|
13.04.2011, 18:46 | 12 |
0
|
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
|
|
13.04.2011, 19:20 [ТС] | 13 |
Deviaphan: Изначально суть такая - Админ, как суперпользователь, в своем методе set может изменять значение поля name в переданном объекте User на второй параметр метода Admin::set.
Единственный вариант, который я тут вижу - это чтобы Get name был char& getname(), т.е. предоставлял совершенно небезопасный доступ к члену, который, кстати, может хоть private - при таком методе по барабану совершенно. Но это плохо. А если говорить об обычном методе getName - а на кой фиг там такой метод нужен? Если в User будет public метод, возвращающий имя и public, разрешающий изменение, то это бред - User не может его менять, как и Manager. Если метод будет protected, то я его вот таким вот образом - в Admin::set - не смогу вызвать так же, как и достать name собственно сейчас. Я могу его сделать виртуальным, но мне от этого ни холодно, ни жарко - вызываться-то он будет для передаваемого объекта, т.е. User или Manager. Просто может там static_cast'ом привести к правильному типу, используя значение enum члена? Решение, которое я вижу - это объявить в User "friend class Admin". Но это бред бредовый - "давайте объявим в родителе то, что дети к нему дружествены и могут достучаться до protected членов".
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|
13.04.2011, 20:07 | 14 |
Тогда у меня один вопрос. Вот, допустим, объект A класса Admin и вот он вызывает функцию set, где первый параметр- указатель p на объект типа User
...Обязательно ли, что бы A был потомком объекта *p? Или необязательно?
0
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|
13.04.2011, 20:16 | 15 |
Если Юзер не может изменять и получать имя, то зачем это поле создано в нём? Зачем объявлять в нём методы, которые не используют это поле? Если объекты Юзер не должны создаваться, класс следует сделать абстрактным. Если Юзеры могут создаваться, но имени у них нет, то и поле name в них не нужно. В общем, очень подозрительная иерархия.
Добавлено через 48 секунд *Не Юзер, а Посетитель. Обчитался.
0
|
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
|
|
13.04.2011, 21:06 | 16 |
Применение защищенных членов-данных и индикаторов типа наводит на мысль, что данный вариант проекта иерархии классов у вас не совсем удачный.
А вы можете саму задачу сформулировать?
0
|
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
|
|
13.04.2011, 21:49 [ТС] | 17 |
В некотором приложении определены следующие классы, определяющие роли пользователей этого приложения:
Visitor - незарегистрированный пользователь User - пользователь с минимальными правами Manager - пользователь с расширенными правами Admin - администратор системы Для любого пользователя системы, за исключением класса Visitor, определены следующие поля: - логин пользователя - массив char[8] - имя пользователя - массив типа char произвольной длины - уровень прав пользователя в системе - целое поле, я его енумом сделал Для каждого определены следующие правила: - Визитор не имеет доступа ни к одному полю даже на чтение - Юзер может только читать свои поля - Менеджер может читать поля любого Юзера, кроме того может читать и менять свои имя и логин - Админ соответственно может менять любое любого пользователя Все классы должны входить в одну иерархию наследования, в которой базовым является Визитор. Все классы должны иметь виртуальные методы void printInfo(User &user) и bool set(User *user, char *name) Инфа о printInfo: - для Визитора - строку ошибки - для Юзера и Менеджера - собственные имя и логин - для Админа - имя и логин того, кто передан по ссылке - ну аргументом функции Инфа о set: - Юзер - Access denied, return false - Manager - замена собственного name - Admin - устанавливает имя того пользователя, указатель на который передается в качестве первого параметра метода, второй параметр - это новое значение. true,false - успешно или нет выполнена операция. Все, текст задания кончился. Фраза про одну иерархию меня натолкнула на то, что одно другое наследует столбиком, хотя наверное Визитор можно сделать базовым для каждого из остальных. Тогда и проблема с протектед членами решится. Далее, насчет переноса аттрибутов - раз уж Визитор будет базовым, логичнее их там оставить имхо.
0
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|
14.04.2011, 06:56 | 19 |
Т.е. это запрещено в самом задании.
А вообще, идиотизм полнейший. Требовать создания отдельных классов только ради различных прав доступа... Преподы меня убивают просто. Хоть это и совершенно тупая иерархия, но поля следует определить в Юзере. В дочерних классах обращаться не напрямую к полю, а через методы.
0
|
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
|
||||||
14.04.2011, 09:47 [ТС] | 20 | |||||
Офф: Ну уж обучение всегда забавно - я тут недавно кодил перегрузку ostream так, чтобы был важен порядок аргументов...
Поля определить в Юзере - т.е. оставить иерархию без изменений? Отлично, а методы-то защищенные или открытые? Защищенные - дык то же, что и с переменными будет) Открытые - это по проектированию бред будет. Т.е. отлично, вот у нас такой набор привилегий, но еще будет два открытых метода к каждому классу, начиная с Юзера, для чтения и изменения привилегий - так что ли сделать?
0
|
14.04.2011, 09:47 | |
14.04.2011, 09:47 | |
Помогаю со студенческими работами здесь
20
Переставить члены последовательности так, чтобы сначала расположились все ее неотрицательные члены Данные, защищенные паролем Защищённые листы в Excel Защищенные видео с YouTube Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |