Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.97/37: Рейтинг темы: голосов - 37, средняя оценка - 4.97
140 / 72 / 26
Регистрация: 29.06.2015
Сообщений: 186
1

Как обратится к обьекту класса, являющегося наследником абстрактного класса

31.07.2015, 23:58. Показов 6943. Ответов 131
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте!
У меня есть 4 класса: один виртуальный, следующие 2 - наследуют виртуальный класс и последний класс содержит
указатель на виртуальный класс (динамический массив, который растет от методов buildCar и buildTruck).
eFuel - это также класс, который содержит еще класс, но в данном вопросе они не принимают участия.
Вопрос: как через указатель четвертого класса доступится к наследующим классам?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class aGasStation
{
    friend class bCar;
    friend class cTruck;
protected :
    double A92;
    double A95;
    double A98;
    int cistern92;
    int cistern95;
    int cistern98;
public:
    aGasStation ();
    ~aGasStation ();
    virtual void print () = 0;
};
 
class bCar : public aGasStation
{
    eFuel fuelcar;
public:
    bCar ();
    ~bCar ();
    void print ();
};
 
class cTruck  : public aGasStation
{
    eFuel fueltruck;
public:
    cTruck ();
    ~cTruck ();
    void print ();
};
 
class dChainOfGasStation
{
    aGasStation *base;
    double money;
    static int size;
public:
    dChainOfGasStation ();
    ~dChainOfGasStation ();
    friend void buildCar (dChainOfGasStation *tmp);
    friend void buildTruck (dChainOfGasStation *tmp);
};
C++
1
2
3
4
5
6
7
8
void main ()
{
    dChainOfGasStation base;
    buildCar (&base);
    buildCar (&base);
    buildTruck (&base);
    buildCar (&base);   
}
Пытаюсь таким способом в main(), но знаю что base[0] - это private, а сделать его public противоречит правилам С++
C++
1
base.base[0]->print();
Можно написать set-метод, но каким образом это сделать я не знаю.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
31.07.2015, 23:58
Ответы с готовыми решениями:

как узнать,является данный объект класса А1 наследником класса А2
Всем привет)есть классы S, A1, A2, B1, B2. Иерархия наследования следующая S - Является...

Как полю класса А обратится к приватной функции класса А?
Есть лифт (класс "Elevator "), в котором находится кнопка (класс "Button"). При нажатии на кнопку...

Как обратиться из конструктора базового абстрактного класса к свойству-массиву класса наследника
Добрый день. Подскажите как обратиться из конструктора базового абстрактного класса к...

Поместить в динамически расширяемый массив объекты класса, производные от базового абстрактного класса
Помогите пожалуйста новичку! (мне). Я хочу создать динамически расширяющийся массив указателей...

131
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 14:24 61
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от DrOffset Посмотреть сообщение
Нарушает инкапсуляцию не friend, а программист, который неправильно его использует.
Ок, а как правильно?
friend в действительности мог бы предлагать больше, и точнее давать возможность задавать более жесткие правила доступа.

Выше я приводил пример с friend, мне нужен был доступ только к закрытым конструкторам классов, вместо этого я получал доступ ко всем закрытым членам.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
01.08.2015, 14:36 62
Цитата Сообщение от Avazart Посмотреть сообщение
мне нужен был доступ только к закрытым конструкторам классов, вместо этого я получал доступ ко всем закрытым членам.
Либо всё, либо ничего. Если хочется получить доступ только к какой-то конкретной части, то нужно эту часть выделить в самостоятельную сущность. Например сделать вложенный класс. Требовать чтобы friend класса имел доступ к ограниченном набору членов этого класса, довольно странно, т.к. это уже был бы и не друг класса вовсе.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 14:37 63
Цитата Сообщение от Tulosba Посмотреть сообщение
Либо всё, либо ничего.
Ну это то как по факту есть, а не так как следовало бы.
Что это как не нарушение инкапсуляции когда предоставляется больше прав чем нужно/предполагается?

Цитата Сообщение от Tulosba Посмотреть сообщение
Если хочется получить доступ только к какой-то конкретной части, то нужно эту часть выделить в самостоятельную сущность.
Как мне "выделить" конструктор?
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.08.2015, 14:37 64
Цитата Сообщение от Avazart Посмотреть сообщение
Ок, а как правильно?
Об этом много где есть.
Например для начала, можно было бы не давать доступ к данным класса всему ChainOfGasStation, а только методу, занимающемуся созданием экземпляра. Т.е. этот метод заменяет собой конструктор + устанавливает отношения взаимодействия и контракт, мы подчеркиваем, что только ChainOfGasStation::addCarGasStation может создать экземпляр. В этом случае не будет нарушения. Т.к. настоящий конструктор тоже имеет доступ ко всем данным - это равноценный обмен.
Уже был аналогичный вопрос, я постарался расписать все подробно (со ссылками на источники, чтобы не быть голословным): https://www.cyberforum.ru/post7804066.html
1
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 14:42 65
Цитата Сообщение от Tulosba Посмотреть сообщение
Требовать чтобы friend класса имел доступ к ограниченном набору членов этого класса, довольно странно, т.к. это уже был бы и не друг класса тогда.
Ну так дела не в соответствии названиию, а в затребованой возможности, как это назвать дело второстепенное.

Добавлено через 2 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
Например для начала, можно было бы не давать доступ к данным класса всему ChainOfGasStation, а только методу, занимающемуся созданием экземпляра.
Вполне логично, так и стоило сделать изначально, я просто не хотел заморачиваться с предъобявления только ради примера.
Но это никак не меняет сути проблемы из того метода нам по прежнему доступны все внутренности, когда нужен только конструктор.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 14:56 66
Цитата Сообщение от Avazart Посмотреть сообщение
Но это никак не меняет сути проблемы из того метода нам по прежнему доступны все внутренности, когда нужен только конструктор.
нету никакой проблемы.
и не нужно её создавать:

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

это - зряшная трата времени и сил.

задача - уберечься лишь от ничайных ошибок.
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.08.2015, 14:57 67
Цитата Сообщение от Avazart Посмотреть сообщение
Вполне логично, так и стоило сделать изначально, я просто не хотел заморачиваться с предъобявления только ради примера.
Тем не менее это важное различие и снижает ценность примера, как доказательства "нарушения инкапсуляции".

Цитата Сообщение от Avazart Посмотреть сообщение
Но это никак не меняет сути проблемы из того метода нам по прежнему доступны все зарытые данные.
Цитата Сообщение от DrOffset Посмотреть сообщение
Т.к. настоящий конструктор тоже имеет доступ ко всем данным - это равноценный обмен.
В этом нет нарушения инкапсуляции. Пересмотри свой взгляд на эту проблему. Метод, который мы определили как friend (addCarGasStation), логически становится частью интерфейса CarGasStation. Нет ничего плохого в том, что ему доступны данные. Он логически - часть класса. Причем декларируем мы это не откуда угодно (тогда бы это было нарушением), а из самого класса CarGasStation, т.к. класс сам себя расширяет на еще один внешний метод. Когда ты добровольно отдаешь что-то - это не воровство, так ведь?
Поэтому Cтрауструп пишет о том, что человек, который пишет про однозначное нарушение инкапсуляции через friend - просто не до конца понимает терминологию С++.

Но если хочется еще больше, то можно разбить наш класс на собственно создающую часть и часть с данными\логикой. Сделать другом только создающую часть, т.к. friend не распространяется на наследование. Техническая возможность ограничить еще больше, существует.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 15:08 68
В данном случае friend как продавец в супермаркете вы покупаете товар, а в место сдачи продавец вам дает жвачку и еще какую фигню которая вам не нада совсем.

Цитата Сообщение от hoggy Посмотреть сообщение
не нужно пытаться сделать убер-защиту класса от злобных хаккеров,
которые будут искать уязвимости в его защите.
Дело не в защите, а логике вешей. Когда говоришь хочу именно это и получаешь что что просишь без всяких довесков.

Цитата Сообщение от hoggy Посмотреть сообщение
задача - уберечься лишь от ничайных ошибок.
Ну так это и дает возможность к ошибится ибо не соблюдается логика.
А человек который читает код должен прилогать большие усилия что бы понять для чего именно тут открыли все потроха...

Если немного пофантазировать то можно было бы придумать что-то вроде:

friend Chain for CarGusStation::CarGusStation();
Добавлено через 6 минут
Остался бы вопрос к целесообразности этого в плане реализации.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 15:13 69
Цитата Сообщение от Avazart Посмотреть сообщение
Дело не в защите, а логике вешей. Когда говоришь хочу именно это и получаешь что что просишь без всяких довесков.
дело в том, что проблема надуманная.
трех простых модификаторов доступа хватает за глаза.

в том числе для установления более жестких контрактов в случае необходимости,
или параноидальности разработчика.

Цитата Сообщение от Avazart Посмотреть сообщение
Ну так это и дает возможность к ошибится ибо не соблюдается логика.
ну вот нужно мне запретить создавать классы кому попало.
я выделил друга - функцию make.
функция make не занимается ничем, кроме создания.

ну и какие здесь проблемы с логикой?

Цитата Сообщение от Avazart Посмотреть сообщение
А человек который читает код должен прилогать большие усилия что бы понять для чего именно тут открыли все потроха...
человек читает: "функция make создает объекты" - это все, что ему нужно знать,
для того, что бы пользоваться.
все остальное - инкапсуляция.

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

Цитата Сообщение от Avazart Посмотреть сообщение
Если немного пофантазировать то можно было бы придумать что-то вроде:
friend Chain for CarGusStation::CarGusStation();
такой подход провоцирует чрезмерное раздутие правил без всякой необходимости.
синтаксис полюсов итак считается перегруженным.

нет причин, грузить его ещё больше вещами,
которые никаких реальных проблем не решают.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 15:17 70
Цитата Сообщение от hoggy Посмотреть сообщение
такой подход провоцирует чрезмерное раздутие правил без всякой необходимости.
синтаксис полюсов итак считается перегруженным.
нет причин, грузить его ещё больше вещами,
которые никаких реальных проблем не решают.
Да ну ладно... я описал проблему и ее решение.
Как по мне значительная часть новшеств С++11 ничего не решает.

Добавлено через 1 минуту
Цитата Сообщение от hoggy Посмотреть сообщение
человек читает: "функция make создает объекты" - это все, что ему нужно знать для того,
Откуда он это читает, он видит фреанд в классе и тут чешит репу...
Потом лезит в этот класс-друг и там смотрит и чешит репу....
И так может метаться кобанчиком от одного к другому несколько раз.
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.08.2015, 15:18 71
Цитата Сообщение от Avazart Посмотреть сообщение
Дело не в защите, а логике вешей. Когда говоришь хочу именно это и получаешь что что просишь без всяких довесков.
Именно так. Логика тут едина. Вот пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Base {};
 
class C : public Base
{
public:
    static std::unique_ptr<C> create()
    {
        std::unique_ptr<C> x(new C());
        x->v = 10;
        return x;
    }
    
private:
    C() {}
    
    int v;
};
Статический метод имеет доступ ко всем данным в классе. Пример компилируется.
Теперь делаем так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Base {};
 
class C : public Base
{
public:
    friend std::unique_ptr<C> create();
   
private:
    C() {}
    
    int v;
};
std::unique_ptr<C> create()
{
    std::unique_ptr<C> x(new C());
    x->v = 10;
    return x;
}
Что изменилось с точки зрения логики? Ничего. Вдумайся в это! Мы просто внесли внешнюю функцию в интерфейс класса. Она стала равноценна функции класса. Внес ее сам класс, он это решил. Здесь нет нарушения инкапсуляции, есть другой подход к организации интерфейса. У него естественно меньший приоритет, потому что он не такой естественный, но логически правила одинаковы.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 15:19 72
Цитата Сообщение от hoggy Посмотреть сообщение
такой подход провоцирует чрезмерное раздутие правил без всякой необходимости.
И не раздутие, а строгость правил.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 15:21 73
Цитата Сообщение от Avazart Посмотреть сообщение
И не раздутие, а строгость правил.
ничем не обоснованное.

вы вообще осознаете,
что по сути то, что вы предлагаете,
это равносильно тому,
что бы отдельным частям класса ограничить доступ к другим частям этого же класса?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 15:26 74
Цитата Сообщение от DrOffset Посмотреть сообщение
Вот пример:
Я чет не понял что пример демонстрирует то?

Добавлено через 47 секунд
Цитата Сообщение от hoggy Посмотреть сообщение
что бы отдельным частям класса ограничить доступ к другим частям этого же класса?
О_о вы наконец то поняли...
Да именно к этому я виду:
{
public only for Chine:
BusGusStation();
}
Но это конечно только фантазии на тему.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 15:27 75
Цитата Сообщение от Avazart Посмотреть сообщение
Откуда он это читает, он видит фреанд в классе и тут чешит репу...
C++
1
2
3
4
5
6
class sample
{
    sample();
 
    friend sample make();     // <--- о боже, и зачем это она френд.
};
Цитата Сообщение от Avazart Посмотреть сообщение
Потом лезит в этот класс-друг и там смотрит и чешит репу....
нафига?

Цитата Сообщение от Avazart Посмотреть сообщение
И так может метаться кобанчиком от одного к другому несколько раз.
нафига?

Добавлено через 1 минуту
Цитата Сообщение от Avazart Посмотреть сообщение
О_о вы наконец то поняли...
теперь осталось и вам понять:
Цитата Сообщение от Avazart Посмотреть сообщение
Я чет не понял что пример демонстрирует то?
потому что именно на этот нюанс пытается обратить ваше внимание господин DrOffset
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.08.2015, 15:33 76
Цитата Сообщение от Avazart Посмотреть сообщение
Я чет не понял что пример демонстрирует то?
Там все написано.
Демонстрирует то, зачем вообще нужен friend. Это альтернативный способ организации интерфейса. Когда мы пишем метод в классе, то почему у нас не возникает желания оставить ему в пользование только часть данных? Сказать: метод x класса А имеет право доступа только к данным а и b класса А, но к данным c и d - не имеет.
Пример демонстрирует, что для friend правила такие же как для членов класса. Точно так же как не существует подобного ограничения для членов класса, не существует его и для friend.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 15:33 77
C++
1
2
3
4
5
 class sample 
{ 
       sample(); 
       friend some::hardcore(); 
}
А если так?
Я не узнаю пока не полезу в hardcore() где увижу что в hardcore() где возможно вызываются закрытые методы и мне опять нужно будет вернуться к классу sample
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 15:35 78
Цитата Сообщение от Avazart Посмотреть сообщение
А если так?
а если так?

C++
1
2
3
4
5
6
7
8
9
class ffsdf
{ 
       ffsdf(); 
       friend ffsdf tyltry(); 
 
int    dfkdflgk;
 
     float dgklhg(int gfg);
};
мож не нужно доводить до маразма?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 15:44 79
Цитата Сообщение от hoggy Посмотреть сообщение
мож не нужно доводить до маразма?
А при чем тут маразм? Дело то не ограничиватеся только созданием(make) могу выполнятся и другие действия.
hardcore() вполне может быть вменяемым названием, но ее имя не скажет точно с чем из защиенных внутренностей данного класса она работает, для этого мне придется листать код к её определению. Т.е менее информативно.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 15:56 80
Цитата Сообщение от Avazart Посмотреть сообщение
А при чем тут маразм? Дело то не ограничиватеся созданием(make) могу выполнятся и другие действия.
1.
пользователя не касается, что там под капотом чужого класса.

2.
разработчик знает, что под капотом его собственного класса.

3.
если функция называется "создавалка", но на деле - "прибивалка",
то у такого кода проблемы посерьезнее,
нежели "отсутствие инкапсуляции от себя самого".

Добавлено через 3 минуты
Цитата Сообщение от Avazart Посмотреть сообщение
hardcore() вполне может быть вменяемым названием, но ее имя не скажет точно с чем из защиенных внутренностей данного класса она работает,
имя функции-члена должно отражать умение механизма.
hardcore в сферическом ваккуме мне ни о чем не говорит, например.

имя не должно никак светить подробности реализации.
0
01.08.2015, 15:56
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.08.2015, 15:56
Помогаю со студенческими работами здесь

Метод абстрактного класса не видит переменные дочернего класса
есть abstract class A{ protected static $dir; public static function f(){} } и два класса...

Вызов функции класса, который наследуется от абстрактного класса
Предположим, что существует класс Base, который является абстрактным class Base{ public:...

Как инициализировать члены класса, являющегося параметром шаблона
#include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std; template &lt;typename SomeClass&gt;...

Как обратится к объекту класса
Не могу обратится к объекту класса по индексу int main() { setlocale(LC_ALL, &quot;RUS&quot;); ...

Как обратиться к конструктору абстрактного класса
В Java это можно сделать таким образом: public abstract class AbClass { AbClass(int a) { }...

Как вызвать функцию из абстрактного класса?
Здравствуйте. Как мне вызвать функцию input с помощью указателя из класса People? При этом не...


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru