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

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

31.07.2015, 23:58. Показов 6949. Ответов 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
70 / 64 / 40
Регистрация: 17.02.2014
Сообщений: 265
01.08.2015, 03:18 41
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Avazart Посмотреть сообщение
А откуда страсть нарушать инкапсуляцию?
В пределах protected не считаю нарушением, мы даем доступ не кому попало а только тому, кому нужно, и особо не заостряю внимание на правильности, только потому, что кто-то описал что так нельзя делать (на заборе тоже написано)
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 03:27 42
Цитата Сообщение от smartpointer Посмотреть сообщение
, мы даем доступ не кому попало а только тому, кому нужно
Вобщето кому попало, ибо- всем наследникам (если конечно вы не собираетесь их потом "скрывать", все 20 штук в каждом наследники "первого уровня")
... хорошо если их всего один уровень, а если больше?

Добавлено через 2 минуты
Цитата Сообщение от smartpointer Посмотреть сообщение
и особо не заостряю внимание на правильности, только потому, что кто-то описал что так нельзя делать (на заборе тоже написано)
В данном случае нет веских оснований что бы делать через protected.
0
70 / 64 / 40
Регистрация: 17.02.2014
Сообщений: 265
01.08.2015, 03:36 43
Цитата Сообщение от Avazart Посмотреть сообщение
Вобщето кому попало, ибо- всем наследникам (если конечно вы не собираетесь их потом "скрывать", все 20 штук в каждом наследники "первого уровня")
... хорошо если их всего один уровень, а если больше?
Вы считаете это косяк программиста или недоработка языка ?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 03:57 44
Цитата Сообщение от smartpointer Посмотреть сообщение
Вы считаете это косяк программиста или недоработка языка ?
А вы как думаете зачем правила?

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
class A
{
   public:
      virtual int value()const{ return v_; };
   protected:
       int v_;
};
 
class B: public A  // *1000
{
   public:
      virtual int value()const{ return v_*1000; };
};
 
 
class C: public B  // еще раз на 1000
{
   public:
     virtual int value()const{ return v_*1000; }; /* Упс, это то что нам надо?!!! */
     //  или возможно хотели это:
     //  virtual  int value()const{ return B::value()*1000; }; 
     //  Логика: 
     //      мы наследуем поведения А или все же B?
};
Добавлено через 16 минут
Ну и с закрытием как вариант с разруливание проблемы

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
class A
{
   public:
      virtual int value()const{ return v_; };
   protected:
       int v_;
};
 
class B: public A  // *1000
{
   public:
      virtual int value()const{ return v_*1000; };
   private:
      using A::v_; /*Решение?  Или все же может лучше сразу сеттеры/геттеры? */
};
 
class C: public B  // еще раз на 1000
{
   public:
     // virtual int value()const{ return v_*1000; }; /* Не позволено! v_  закрыт */
     //  или возможно хотели это:
     virtual  int value()const{ return B::value()*1000; }; 
     //  Логика: 
     //      мы наследуем поведения А или все же B?
};
3
60 / 11 / 4
Регистрация: 09.09.2014
Сообщений: 182
01.08.2015, 04:59 45

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
А откуда страсть нарушать инкапсуляцию мотивируя расходом памяти?
Очень смахивает на сектантскую фразу ;D



Добавлено через 27 минут
Цитата Сообщение от Avazart Посмотреть сообщение
или возможно хотели это:
* * *// *virtual *int value()const{ return B::value()*1000; };
* * *// *Логика:
* * *// * * *мы наследуем поведения А или все же B?
Неужели. Протрезвили. Если я правильно понимаю, при наследовании не-private-члена он создается в экзмепляре в количестве равном количеству наследований + 1 ( base > s1 > s2 - в s2 будет 3 экземпляра свойства X, что прямо противоречит не правилам инкапсуляции, а законам мироздания ). А private-члены создаются в единственном экземпляре в суперклассе. Чего нельзя сказать о методах ( если свойство одно, то методов работы с ним множество ), что обуславливает возможность сохранения их со всех предков и желаемый доступ, либо внутри класса, либо открытый, либо закрыть для следующих наследников ( типа устаревший для современности ). Если так, то с этого надо было начинать, а то: "инкапсуляция, инкапсуляция..."
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 05:23 46
Цитата Сообщение от Eraston Посмотреть сообщение
Очень смахивает на сектантскую фразу
Avazart - прав.
всем остальным - читать Макконелла.

если Макконелл не поможет - уже ничто не поможет.

зы:

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

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

пример:

допустим, есть кнопка (библиотечный класс),
и нужно посетить реакцию на клик:

http://rextester.com/GBPX73313

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
#include <iostream>
#include <functional>
 
 
struct Button
{
    typedef std::function<void()>
        Event;
    
    
    Event eventClick;
    
    void SimulateClick()
    {
        if(eventClick)
            eventClick();
    }
 
};
 
 
void OnClick()
{
    std::cout<<"button was click\n";
 
}
 
int main()
{
    std::cout << "Hello, world!\n";
    
    Button bt;
    
    bt.eventClick = OnClick;
    
    bt.SimulateClick();
}
делать сеттер в этой ситуации не имеет смысла.
потому что весь дизайн уже задал std::function.
и сеттеру тупо нечем было бы заниматься.
в принципе.
0
60 / 11 / 4
Регистрация: 09.09.2014
Сообщений: 182
01.08.2015, 05:24 47
Собственно, теперь понял, почему размер классов у меня рос с прогрессией 16 48 104, вместо 16 40 64.
Avazart, спасибо за терпение, обсуждение и примеры.
0
Эксперт С++
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
01.08.2015, 06:39 48
Цитата Сообщение от hoggy Посмотреть сообщение
делать сеттер в этой ситуации не имеет смысла.
потому что весь дизайн уже задал std::function.
и сеттеру тупо нечем было бы заниматься.
в принципе.
Не знаю, здесь мне кажется более феншуйным передавать указатель на функцию как аргумент либо конструктору кнопки, либо функции SimulateClick.
0
70 / 64 / 40
Регистрация: 17.02.2014
Сообщений: 265
01.08.2015, 06:59 49
Цитата Сообщение от Avazart Посмотреть сообщение
мы наследуем поведения А или все же B?
Конструктор специально убрали. В объявлении C явно указано public B - а следовательно, переопределяя дефолтный конструктор мы можем явно вызвать только конструктор B. Класс C еще ничего не знает про A, точнее знает поскольку декларация уже произошла, но не знает что это дедушка для него, выясняется это только, когда конструктор B вызвал конструктор A,а C вызвал B. Все тоже самое происходит даже если мы не определяли конструктор, ибо подставится компилятором.В итоге класс C увидит у класса B все, что у него там унаследовано от отца.
Теперь развиваем магию над int v_ в C заносим (только первый вариант кода).
C++
1
2
3
4
5
6
void Print()
{
    std::cout<< &(A::v_) << std::endl;
    std::cout<< &(B::v_) << std::endl;
    std::cout<< &(C::v_) << std::endl;
}
Что видим - адреса одинаковые, следовательно никаких копий - это собственность A, и никакого роста памяти! Но кстати за using спасибо, первый раз вижу такой хак
0
Эксперт С++
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
01.08.2015, 07:02 50
Цитата Сообщение от irises Посмотреть сообщение
этот класс будет управлять сетью заправок, с помощью методов, которые показала выше - буду добавлять новые заправки
и вот через этот главный класс хочу организовать заправку машин и подачу бензина на заправку (тоесть уход и приход бензина) через абстрактный класс
Вообще-то проектировать надо начинать с интерфейсных функций, а не с данных. А зачем вам абстрактная заправка понадобилась? Это в задании так или вы сами придумали?
1
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 07:48 51
Цитата Сообщение от Mr.X Посмотреть сообщение
Не знаю, здесь мне кажется более феншуйным передавать указатель на функцию как аргумент либо конструктору кнопки
лепить громоздкий вариадик-конструктор,
который на самом деле тупо делегирует все std::function?

на крайняк конструктор может принимать std::function,
а не указатель-на-функцию.
это позволит избежать шаблоно-кода,
и не придется ограничивать функционал только лишь указатель-на-функцию.

ну ок. слепили.

и тут проблема:
у кнопки может быть до чертиков разных событий:
CLICK, DCLICK, PASSED,HOVER,OUT - это лишь джентельменский набор.

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

и что осталось от вашего феншуя?

--------------

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

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

но никто в здравом уме не делает кастомизацию в конструкторах.
0
Эксперт С++
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
01.08.2015, 10:20 52
Цитата Сообщение от hoggy Посмотреть сообщение
лепить
Цитата Сообщение от hoggy Посмотреть сообщение
ну ок. слепили
Цитата Сообщение от hoggy Посмотреть сообщение
но никто в здравом уме не делает
Ну вот сразу видно благородного и воспитанного джентльмена! Охотно бы поспорил, но в моем лексиконе просто нет столь же изысканных выражений.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 11:17 53
hoggy, Ну впринципе да всегда могут быть исключения, стоит смотреть по месту, но мне кажется все же стоит думать о том как спрятать - Signals2
Ибо открытым мы делает все же объект, в том время как в нем может быть больше возможностей чем нам хотелось бы показать.

Что касается исключения- паттерн property
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 11:28 54
Цитата Сообщение от Avazart Посмотреть сообщение
но мне кажется все же стоит думать о том как спрятать
плохой путь.
именно это я и называю "громоздкой вариадик шаблоно-функцией"
и начинается:
1. под методы
2. под свободные функи.
3. под функторы.

велосипедирование функционала std::function.

нафига?

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

решение уже является законченным дизайном.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 11:37 55
Цитата Сообщение от hoggy Посмотреть сообщение
решение уже является законченным дизайном.
Ну в std::function есть оператор вызова, вполне может оказаться что мы бы не хотели что бы пользователь имел возможность использовать его напряму менуя метод. Кстати как быть с наследованием на примере иерархии A/B/C если открывать std::function?

C++
1
bt.eventClick();// вместо bt.SimulateClick()
Естетственно это "натянуто", но я как понял мы говорим в общем и не только о std::function

Добавлено через 5 минут
В boost::signals2 куда больше возможностей и не все охота их показывать/допускать.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.08.2015, 11:47 56
Цитата Сообщение от Avazart Посмотреть сообщение
не хотели что бы пользователь имел возможность использовать его напряму менуя метод.
ну если так, тогда выбора не остается - придется прятать в приватах.

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

выглядит не очень читабельно,
но это уже на совести пользователя.
если что нибудь пойдет не так,
std::function сам отобьется (бросит исключение, etc).
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 12:10 57
Цитата Сообщение от smartpointer Посмотреть сообщение
A, и никакого роста памяти!
Это рост памяти? Ну ну продолжайте экономить на спичках...

Цитата Сообщение от smartpointer Посмотреть сообщение
Конструктор специально убрали. В объявлении C явно указано public B - а следовательно, переопределяя дефолтный конструктор мы можем явно вызвать только конструктор B.
Чет не понял зачем там конструктор. Вообще не понял про конструктор.
Цитата Сообщение от smartpointer Посмотреть сообщение
В итоге класс C увидит у класса B все, что у него там унаследовано от отца.
Спасибо кеп, я вообщето и показал что он видит то что ему не нужно видеть что черевато ошибками.

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

Добавлено через 16 минут
Цитата Сообщение от Mr.X Посмотреть сообщение
указатель на функцию как аргумент либо конструктору кнопки, либо функции SimulateClick.
Ну SimulateClick может и вообще не быть, т.е вызов может происходить при получении сообщения от системы.
Конструктор- будет жестко задавать "обработчик" нельзя будет его менять в рантайме.

P.S.: std::function кстати подходит не лучшим способом ибо не исключает вероятности что будет ссылаться на удаленный объект, поэтому я и упамянул boost::signals2.
0
60 / 11 / 4
Регистрация: 09.09.2014
Сообщений: 182
01.08.2015, 12:25 58
Цитата Сообщение от smartpointer Посмотреть сообщение
Что видим - адреса одинаковые, следовательно никаких копий - это собственность A, и никакого роста памяти!
Не знаю, у меня при наследовании классы росли не соотвествующе увеличению количества переменных - больше.

Цитата Сообщение от Avazart Посмотреть сообщение
Это рост памяти? Ну ну продолжайте экономить на спичках...
Это смотря как посмотреть. Наша планета тоже спичка в Галактике, но и в этой спичке море интересного. Грамотный программист найдет оптимальный режим между объемом занимаемой памяти и нагрузкой на процессор (то и не удивительно, что "калькулятор", вдруг оказывается, затребляет по 500 Мб ОЗУ непонятно зачем)

Цитата Сообщение от Avazart Посмотреть сообщение
инкапсуляцию
В таком случае еще более острым становится вопрос, объявленный в этой теме, поскольку она не только не объединяет данные, а скорее разъединяет их с таким уровнем доступа, что не есть гуд.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.08.2015, 13:18 59
Цитата Сообщение от Eraston Посмотреть сообщение
поскольку она не только не объединяет данные,
Объединяет логически связанные данные, из чего очевидно:
Цитата Сообщение от Eraston Посмотреть сообщение
, а скорее разъединяет
Что не связано...
Увидел треш с #pragma pack(push, 4) в классах не стал читать.
0
18895 / 9853 / 2410
Регистрация: 30.01.2014
Сообщений: 17,296
01.08.2015, 14:18 60
Цитата Сообщение от Avazart Посмотреть сообщение
А что расказывать friend нарушает инкапсуляцию
Со всем согласен, кроме этого. Нарушает инкапсуляцию не friend, а программист, который неправильно его использует.
Собственно, об этом Страуструп высказывался довольно четко:
I have never been able to see the recurring assertions that a friend declaration "violates encapsulation" as anything but a combination of ignorance and confusion with non-C++ terminology.
0
01.08.2015, 14:18
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.08.2015, 14:18
Помогаю со студенческими работами здесь

Метод абстрактного класса не видит переменные дочернего класса
есть 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? При этом не...


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

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