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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 18, средняя оценка - 4.72
irises
69 / 26 / 8
Регистрация: 29.06.2015
Сообщений: 104
#1

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

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

Здравствуйте!
У меня есть 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-метод, но каким образом это сделать я не знаю.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.07.2015, 23:58     Как обратится к обьекту класса, являющегося наследником абстрактного класса
Посмотрите здесь:
как узнать,является данный объект класса А1 наследником класса А2 C++
C++ Как полю класса А обратится к приватной функции класса А?
C++ Поместить в динамически расширяемый массив объекты класса, производные от базового абстрактного класса
Как инициализировать члены класса, являющегося параметром шаблона C++
C++ Как организовать интерфейс в виде абстрактного класса?
C++ Использование конструктора базового класса наследником
C++ Запрет shared_ptr быть наследником определённого класса
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
7058 / 4199 / 949
Регистрация: 30.01.2014
Сообщений: 6,965
01.08.2015, 18:10     Как обратится к обьекту класса, являющегося наследником абстрактного класса #91
Цитата Сообщение от Avazart Посмотреть сообщение
Да я код читаю, из него ничего не понять что вы хотели продемонстировать... пример фиг знает чего, ради не знаю чего.
Там еще текст был. И этот текст связан причинно-следственной связью с предыдущим обсуждением и конкретно твоими словами об ограничении на доступ для friend конкретных полей или функций:
Цитата Сообщение от Avazart Посмотреть сообщение
friend Chain for CarGusStation::CarGusStation();
Этот пример поясняет логику, которая применяется для friend. Показывает что из себя friend представляет. Потому что попытка задуматься о таком, как в цитате выше, показывает, что ты неправильно понимаешь назначение friend в языке. Ты его воспринимаешь как "раскрывашку" данных кому не попадя, когда на самом деле это всего-лишь дополнительный способ описания интерфейсов. А неправильное применение как раз вытекает из понимания friend как простой раскрывашки данных. Если мы начнем относится к friend функциям\классам как к части интерфейса, то все станет на свои места.
hoggy
6437 / 2655 / 460
Регистрация: 15.11.2014
Сообщений: 5,844
Завершенные тесты: 1
01.08.2015, 18:52     Как обратится к обьекту класса, являющегося наследником абстрактного класса #92
Цитата Сообщение от Avazart Посмотреть сообщение
Да я код читаю, из него ничего не понять что вы хотели продемонстировать... пример фиг знает чего, ради не знаю чего.
там в обоих случаях дизайн принципиально не отличается.
различие лишь в незначительных технических деталях:

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
47
48
49
50
#include <iostream>
#include <memory>
 
// --- найдите 10 принципиальных отличий
 
class Base {};
 
 
class C1 : public Base
{
public:
    static std::unique_ptr<C1> create()
    {
        std::unique_ptr<C1> x(new C1);
        x->v = 10;
        return x;
    }
    
private:
    C1() {}
    int v;
};
 
class C2 : public Base
{
public:
    friend std::unique_ptr<C2> create();
   
private:
    C2() {}
    
    int v;
};
std::unique_ptr<C2> create()
{
    std::unique_ptr<C2> x(new C2);
    x->v = 10;
    return x;
}
 
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    // --- смотреть на дизайн использования:
    auto obj1 = C1::create();
    auto obj2 = create();
}
в обоих случаях, создание объекта в обход фабрики запрещен.
в обоих случаях, в качестве фабрики использованы свободные функции.
в обоих случаях они - часть интерфейса класса

единственная разница в том,
что статическая-функция член существует в пространстве имени своего класса

а функция друг - вне пространства имени класса.

никаких других отличий в данном случае нет вообще.

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

недаром, что функцию член можно определить прямо в теле декларации класса:

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
47
48
49
50
51
52
53
#include <iostream>
#include <memory>
 
// --- найдите 10 принципиальных отличий
 
class Base {};
 
 
class C1 : public Base
{
public:
    static std::unique_ptr<C1> create()
    {
        std::unique_ptr<C1> x(new C1);
        x->v = 10;
        return x;
    }
    
private:
    C1() {}
    int v;
};
 
class C2 : public Base
{
public:
    friend std::unique_ptr<C2> create()
    {
        std::unique_ptr<C2> x(new C2);
        x->v = 10;
        return x;
    }
 
   
private:
    C2() {}
    
    int v;
};
std::unique_ptr<C2> create();
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    // --- смотреть на дизайн использования:
    
    auto obj1 = C1::create();
    
    auto obj2 = create();
    
}

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

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

и есть манагер, в который вынесена вся логика организации связей.

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

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

однако, я противник подобного дизайна:
C++
1
2
3
4
5
6
7
    Graph g;
    Vertex* v1= g.addVertex();
    Vertex* v2= g.addVertex();
 
    Edge* e= g.addEdge(v1,v2); //<--- закатали указатель
 
    delete v1; //ой, а чего это мы тут прибили ненароком?
C++
1
2
3
4
5
6
7
8
9
Edge *DependencyManager::createEdge(Graph *graph, Vertex *from, Vertex *to)
{
   assert(graph && from!=to && graph==from->graph_ && graph==to->graph_);
   Edge* edge= new Edge(graph,from,to);
   graph->edges_.push_back(edge);
   from->outEdges_.push_back(edge);   //<--- вах! вах!!! 
   to->inEdges_.push_back(edge);
   return edge;
}
нарушение правила:
кто захватывал, тот и должен освобождать.

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

C++
1
2
3
4
5
    
    Graph g;
    Vertex& v1= g.addVertex();
    Vertex& v2= g.addVertex();
    g.addEdge(v1,v2);
Avazart
Эксперт С++
7121 / 5298 / 273
Регистрация: 10.12.2010
Сообщений: 23,443
Записей в блоге: 17
01.08.2015, 19:01     Как обратится к обьекту класса, являющегося наследником абстрактного класса #93
Цитата Сообщение от hoggy Посмотреть сообщение
нарушение правила:
кто захватывал, тот и должен освобождать.
Так в том то и дело что нет явного владельца. Ибо логично что ребро не может сущетвовать отдельно от графа и от двух вершин которые оно соединяет.
Касательно указателя указателя так так и должно быть, указатель в обычных случаях может стать невалидным (Удаляем "родителя" удаляются "дочки", в данном случае у ребра два родителя, а с учетом графа - три)
irises
69 / 26 / 8
Регистрация: 29.06.2015
Сообщений: 104
01.08.2015, 19:02  [ТС]     Как обратится к обьекту класса, являющегося наследником абстрактного класса #94
Цитата Сообщение от Mr.X Посмотреть сообщение
А зачем вам абстрактная заправка понадобилась? Это в задании так или вы сами придумали?
это такое задание

Создать консольное приложение, в котором реализовать работу сети автозаправок.
Заправки есть двух видов:
- Для легковых авто;
- Для грузовых авто.
Каждая заправка работает с тремя видами топлива: "А-92", "А-95", "А-98". Каждая заправка имеет ограниченный объем резервуара для хранения каждого вида топлива.
Функциональность сети:
1. Поставка топлива (отдельного вида отдельного заправку). Фиксируется дата поставки.
2. Отгрузка топлива (отдельного вида с отдельной заправки). Фиксируется дата отгрузки.
3. Просмотр статистики по каждой заправке: сколько запасов по видам топлива, история отгрузки пиломатериал по датам.
Все данные по запасам хранятся в файле.
Все данные по истории отгрузки хранятся в файле (другому).
4. Отчет по количеству отгруженного топлива (без деления по видам) по каждой заправке на конкретную дату (дата вводится пользователем). Определение заправки с максимальным показателем по отгрузке на конкретную дату (без деления по видам).

Реализовать абстрактный класс "Заправка". От него унаследовать два класса, которые представляют два вида заправок.
Реализовать класс "Сеть заправок".
Реализовать класс "Топливо".
Реализовать класс "Дата".
Реализовать обработку исключительных ситуциаций: попытки залить топлива больше, чем можно хранить, попытки отгрузить горючего больше, чем есть на заправке (по видам топлива).
Использовать библиотеку STL.
Проект должен быть разбит на header и cpp файлы. Каждый класс в отдельном файле.
Метод main () в отдельном файле.
Все данные загружать из файла.
Работу программы организовать в виде эргономичного меню.
Avazart
Эксперт С++
7121 / 5298 / 273
Регистрация: 10.12.2010
Сообщений: 23,443
Записей в блоге: 17
01.08.2015, 19:15     Как обратится к обьекту класса, являющегося наследником абстрактного класса #95
hoggy, Я с этой специально и привел пример с сильносвязными объектами.

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

Добавлено через 3 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
Ты его воспринимаешь как "раскрывашку" данных кому не попадя, когда на самом деле это всего-лишь дополнительный способ описания интерфейсов.
В этом и проблема что как раз четко описать/зафиксировать интерфейс общенния/связей в нужной мере для двух и более классов нет возможностей.

Добавлено через 1 минуту
Цитата Сообщение от hoggy Посмотреть сообщение
я за то, что бы не использовать указатели там,
где по смыслу ожидаются живые объекты.
Ну так чет не уловил, в чем суть замены указателей ссылками?
hoggy
6437 / 2655 / 460
Регистрация: 15.11.2014
Сообщений: 5,844
Завершенные тесты: 1
01.08.2015, 19:45     Как обратится к обьекту класса, являющегося наследником абстрактного класса #96
Цитата Сообщение от Avazart Посмотреть сообщение
Ну полноценной она вряд ли может быть (хотя бы из выноса из пространства имен) и даже так, а как тогда трактовать дружественный класс?
ну вот взять например, итератор:
C++
1
сontainer::iterator it = cont.begin();
формально - это отдельный класс от контейнера.
но логически (и на практике) - это часть интерфейса самого контейнера.

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

например, никто не сделает ничайно delete ссылке,
которую вернула функция.

и у пользователя не возникнет сомнений
касательно прав владения ресурсом.
Avazart
Эксперт С++
7121 / 5298 / 273
Регистрация: 10.12.2010
Сообщений: 23,443
Записей в блоге: 17
01.08.2015, 20:08     Как обратится к обьекту класса, являющегося наследником абстрактного класса #97
Цитата Сообщение от hoggy Посмотреть сообщение
но логически (и на практике) - это часть интерфейса самого контейнера.
Нет это не так.
Это прослойка/интерфейс между контейнерами и алгоритмами. Т.е нечто то что смещенно в сторону алгоритмов.
Само по себе существование итератора в отрыве от алгоритмов - нелепо. Как к примеру и friend оператор.
friend это такие себе "мостики" между несколькими "сущностями".

И пример DrOffset с использованием friend мне не понятен, мне кажется это необоснованным тем более кода есть альтернатива со статическим методом.
Да смысла в том что запрещать использования создания через конструктор я не уловил.
Только для запрета копирования? Так есть для этого прием NonCopyable причем которые не запрещает создавать объекты "не динамически".

Если подразумевалась фабрика/фабричный метод, так там по сути несколько классов, т.е дружественность на своем месте, месте "посредника". Хотя там и без дружественности вероятно можно обойтись...
hoggy
6437 / 2655 / 460
Регистрация: 15.11.2014
Сообщений: 5,844
Завершенные тесты: 1
01.08.2015, 20:13     Как обратится к обьекту класса, являющегося наследником абстрактного класса #98
Цитата Сообщение от Avazart Посмотреть сообщение
Так в том то и дело что нет явного владельца. Ибо логично что ребро не может сущетвовать отдельно от графа и от двух вершин которые оно соединяет.
Касательно указателя указателя так так и должно быть, указатель в обычных случаях может стать невалидным (Удаляем "родителя" удаляются "дочки", в данном случае у ребра два родителя, а с учетом графа - три)
владелец - граф.
который является контейнером для всех этих ребер и вершин.

он создает вершины/ребра.
он и должен их прибивать.

обратите внимание:
C++
1
Vertex(Graph* graph):graph_(graph){}
C++
1
Edge(Graph* graph,Vertex* from,Vertex* to);
элементы контейнера не самостоятельны.
они в принципе не могут существовать отдельно от своего графа.

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

наружу, как и любой другой нормальный контейнер,
граф выдает только ссылки на свои элементы.

и никто снаружи по этим ссылкам не должен их прибивать.
хорошая новость в том, что delete ссылкам не делают.
Avazart
Эксперт С++
7121 / 5298 / 273
Регистрация: 10.12.2010
Сообщений: 23,443
Записей в блоге: 17
01.08.2015, 20:22     Как обратится к обьекту класса, являющегося наследником абстрактного класса #99
Ок тогда как вы предполагаете убивать Vertex и Edge если не через delete ?
hoggy
6437 / 2655 / 460
Регистрация: 15.11.2014
Сообщений: 5,844
Завершенные тесты: 1
01.08.2015, 20:27     Как обратится к обьекту класса, являющегося наследником абстрактного класса #100
Цитата Сообщение от Avazart Посмотреть сообщение
Это прослойка/интерфейс между контейнерами и алгоритмами. Т.е нечто то что смещенно в сторону алгоритмов.
забудьте на минуту слово "алгоритм".
оно вам только глаз замыливает.


есть контейнер.
и есть вызывающая сторона.
которая может выполнять манипуляции над контейнером.

все действия над контейнером осуществляются
посредством его интерфейса.

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

это можно сделать, дернув напрямую функцию-член.
или дернув итератор.


а в том что касается алгоритмов:

в итераторы вынесли нечто общее для всех контейнеров.
и стандартизировали.

то есть, алгоритмы тупо закладываются на интерфейс контейнеров.

Цитата Сообщение от Avazart Посмотреть сообщение
И пример DrOffset с использованием friend мне не понятен
я уже не знаю, как вам ещё помочь это понять.

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

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

Цитата Сообщение от Avazart Посмотреть сообщение
Да смысла в том что запрещать использования создания через конструктор я не уловил.
а это вообще не существенно для примера-иллюстрации.

Добавлено через 54 секунды
Цитата Сообщение от Avazart Посмотреть сообщение
Ок тогда как вы предполагаете убивать Vertex и Edge если не через delete ?
так же как и создавались - через граф.
Mr.X
Эксперт С++
3048 / 1693 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
01.08.2015, 20:56     Как обратится к обьекту класса, являющегося наследником абстрактного класса #101
Цитата Сообщение от irises Посмотреть сообщение
это такое задание
Начните с разработки меню. А там что, предполагается какая-то имитация работы в реальном времени?
Avazart
Эксперт С++
7121 / 5298 / 273
Регистрация: 10.12.2010
Сообщений: 23,443
Записей в блоге: 17
01.08.2015, 21:16     Как обратится к обьекту класса, являющегося наследником абстрактного класса #102
Цитата Сообщение от hoggy Посмотреть сообщение
забудьте на минуту слово "алгоритм".
оно вам только глаз замыливает.
Ну глупо отрывать от контекста.
Цитата Сообщение от hoggy Посмотреть сообщение
это можно сделать, дернув напрямую функцию-член.
или дернув итератор.
Вопрос в том накой мне итератор когда есть "обычный" доступ?
Ответ- нафиг сдался, итератор нужен алгоритмам как способ обобщения.


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

Не по теме:


Добавлено через 12 минут

Цитата Сообщение от hoggy Посмотреть сообщение
так же как и создавались - через граф.
Ну не знаю. К примеру в Qt не так реализовано, там через delete, а методы removeXXX просто удаляют из внутренних списков, т.е передают владение.
Правда там нет запрета создания через коструктор.

smartpointer
67 / 61 / 23
Регистрация: 17.02.2014
Сообщений: 256
01.08.2015, 21:21     Как обратится к обьекту класса, являющегося наследником абстрактного класса #103
Цитата Сообщение от hoggy Посмотреть сообщение
2.
в примере выше у класса был закрыт конструктор.
автор этого кода сделал это специально.
Цель была запретить создание объекта из-вне, но не запрещать наследоваться - разница все же очевидна не так ли ? Решение проблемы protected конструкторы - из-вне мы их так же не сможем вызвать, зато наследоваться сможем
hoggy
6437 / 2655 / 460
Регистрация: 15.11.2014
Сообщений: 5,844
Завершенные тесты: 1
01.08.2015, 21:29     Как обратится к обьекту класса, являющегося наследником абстрактного класса #104
Цитата Сообщение от smartpointer Посмотреть сообщение
но не запрещать наследоваться - разница все же очевидна не так ли ?
вы ошибаетесь.
запрет и на наследование тоже.

иначе конструктор был бы protected, а не private.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.08.2015, 21:47     Как обратится к обьекту класса, являющегося наследником абстрактного класса
Еще ссылки по теме:
Как при помощи указателя на базовый класс обратится к полю наследуемого класса? C++
как исправить Ошибка 8 error C2259: Tabl: невозможно создать экземпляр абстрактного класса C++
Создание объекта класса, являющегося суммой 2ух других C++
Объекты абстрактного класса C++
Реализация абстрактного класса C++

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

Или воспользуйтесь поиском по форуму:
smartpointer
67 / 61 / 23
Регистрация: 17.02.2014
Сообщений: 256
01.08.2015, 21:47     Как обратится к обьекту класса, являющегося наследником абстрактного класса #105
Цитата Сообщение от hoggy Посмотреть сообщение
вы ошибаетесь.
запрет и на наследование тоже.
Да ну, а если мне важно от него унаследоваться ? Допустим этот класс библиотечный, может юзер сам решит наследоваться от него или нет ?
Yandex
Объявления
01.08.2015, 21:47     Как обратится к обьекту класса, являющегося наследником абстрактного класса
Ответ Создать тему
Опции темы

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