Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.52/29: Рейтинг темы: голосов - 29, средняя оценка - 4.52
0 / 0 / 0
Регистрация: 07.10.2019
Сообщений: 78
1

Как создать полиморфный массив?

15.03.2020, 23:44. Показов 5957. Ответов 36
Метки c++ (Все метки)

Author24 — интернет-сервис помощи студентам
Есть классы A, B, C. А - класс-родитель. B и C дочерние, наследуют от него полный функционал. Как создать массив, который будет в себе иметь обьекты всех типов и как инициализировать элементы такого массива по индексу?(Желательно с примером, но без template и vector, обычные структуры или классы).
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.03.2020, 23:44
Ответы с готовыми решениями:

Создать полиморфный объект и продемонстрировать работу функций
Есть классы: class A { public: virtual void f() {} }; class B : public A { public:...

На базе набора функций создать полиморфный класс
#include <iostream> #include <math.h> #include <windows.h> #include <iomanip> using namespace...

Как создать динамический массив типа string? Как создать класс такого массива?
Как создать динамический массив типа string? Как создать класс такого массива? =-O Помогите,...

Полиморфный массив
Как задать динамический массив из float и того, что было определено в typedef-e? typedef обычная...

36
0 / 0 / 0
Регистрация: 07.10.2019
Сообщений: 78
16.03.2020, 10:28  [ТС] 21
Author24 — интернет-сервис помощи студентам
У меня два вопроса.
Цитата Сообщение от L0M Посмотреть сообщение
case 0: arr[i] = new A((int)i); break;
            case 1: arr[i] = new B((int)i); break;
            case 2: arr[i] = new C((int)i); break;
1)Это разве не принцип создания матрицы, когда каждый элемент есть началом массива?Если да, тогда почему так?

Цитата Сообщение от L0M Посмотреть сообщение
for (size_t i = 0; i < ARRLEN; ++i) {
        arr[i]->iAm();
    }
2)Если класс-родитель не абстрактный, то есть чистых функций у него нету и в одном из дочерних классов не инициализировать метод iAm(), но вызвать его(метод iAm) циклом для всех элементов, компилятор выдаст ошибку, так как либо в В или С он не инициализирован?Если да, то как избежать этой ошибки?
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
16.03.2020, 10:49 22
Цитата Сообщение от L0M Посмотреть сообщение
Попробую ещё раз. Массив, как структура данных, - вещь очень низкоуровневая. Массив - это непрерывная область памяти, состоящая из набора подобъектов одинакового типа.
L0M, это необходимое но не достаточное условие, для массива - типа. С точки зрения монолитности, да - горную или лесистую, местность, называют массивом. Столешницу из натурального дуба (данная тема требует сильных аналогий) тоже называют массивом. Но блок памяти в С++ массивом не является. Хотя называют его так частенько. И когда условность такого применения слову "массив" подразумевается, это допустимо. Однако в С++ есть 2 массива - C-style array и std::array<T>. Оба имеют размер времени компиляции.
По духу задания, ТС нужен блок в динамической памяти, так как речь о функционале поддерживающем полиморфную коллекцию. И если коллекция подразумевает свободный набор подтипов, то освободить её от ограничений размера вполне логично.
Однако ТС отказывается от шаблонных контейнеров и вы правы в том, что суть вопроса легко показать на простом. И это массив.
А суть в полиморфной природе объекта и если идти от "рекомендаций", то контейнер unique_ptr был бы хорош. Но новичку это не надо (по его заявлению).
А дух вопроса не понят вами полудух, даже на половину. А упрямства хватает на четверых.
0
daslex
16.03.2020, 12:28
  #23

Не по теме:

полудух, есть термины быта и есть термины языка. В терминах языка массивы — это T[] и array<T>.
Под капотом у вектора указатель на массив. А массив и указатель совершенно разные сущности.

0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,284
16.03.2020, 12:48 24

Не по теме:

Вообще не понятно к чему этот спор о терминах, если ТС сам попросил решение без вектора в частности и шаблонов вообще? :)



Eg0ra1, лучше покажите на примере ваши затруднения, т.к. терминологию употребляете невпопад, поэтому трудно понять точно что у вас не так.
0
daslex
16.03.2020, 12:51
  #25

Не по теме:

полудух,

C++
1
vector<int> f(){    return vector<int>{1,2,3,4,5};  } //по правилам языка нельзя возвращать из функций массивы (8.3.4 1: тип функции не должен быть типом массив)

0
0 / 0 / 0
Регистрация: 07.10.2019
Сообщений: 78
16.03.2020, 13:07  [ТС] 26
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
 
ifstream file("file.txt");
 
class Exhibit {
protected:
    string name;
    string author;
    int price;
    int year;
public:
    Exhibit() :name("none"), author("unknown"), price(0), year(0) {};
    Exhibit(string n, string a, int p, int _a) {
        name = n;
        author = a;
        price = p;
        year = _a;
    }
    Exhibit(const Exhibit& l) {
        name = l.name;
        author = l.author;
        price = l.price;
        year = l.year;
    }
};
 
class Sculpture : public Exhibit {
    string material;
public:
    Sculpture() :material("wood"), Exhibit() {}
    Sculpture(string n, string a, float p, short y, string m) :Exhibit(n, a, p, y) {
        material = m;
    }
    Sculpture(const Sculpture& l) :Exhibit(l) {
        material = l.material;
    }
    friend istream& operator>>(istream& in, Sculpture& l);
    friend ostream& operator<<(ostream& out, const Sculpture& l);
};
 
istream& operator>>(istream& in, Sculpture& l) {
    in >> l.name >> l.author >> l.price >> l.year >> l.material;
    return in;
}
ostream& operator<<(ostream& out, const Sculpture& l) {
    out << "Name: " << l.name << endl
        << "Author: " << l.author << endl
        << "Price: " << l.price << endl
        << "Year: " << l.year << endl
        << "Material: " << l.material << endl << endl;
    return out;
}
 
class Picture : public Exhibit {
    string genre;
public:
    Picture() :genre("classic"), Exhibit() {}
    Picture(string n, string a, float p, short y, string c) :Exhibit(n, a, p, y) {
        genre = c;
    }
    Picture(const Picture& l) :Exhibit(l) {
        genre = l.genre;
    }
    friend istream& operator>>(istream& in, Picture& l);
    friend ostream& operator<<(ostream& out, const Picture& l);
};
 
istream& operator>>(istream& in, Picture& l) {
    in >> l.name >> l.author >> l.price >> l.year >> l.genre;
    return in;
}
ostream& operator<<(ostream& out, const Picture& l) {
    out << "Name: " << l.name << endl
        << "Author: " << l.author << endl
        << "Price: " << l.price << endl
        << "Year: " << l.year << endl
        << "Genre: " << l.genre << endl << endl;
    return out;
}
 
int main() {
    try {               
        if (!file) {
            throw 1;
        }
    }
    catch(int a){
        cout << "Error " << a << " - File isn't opened.\n";
        system("pause");
        return 0;
    }
    string symbol = "";
    int size = 0;
    while (!file.eof()) {           
        file >> symbol;
        if(symbol == "#"){
            cout << "Picture\n";
            size++;
        }
        else if (symbol == "$") {
            cout << "Sculpture\n";
            size++;
        }
    }
    file.clear();
    file.seekg(0);
          // полиморфный массив
}
В последней строчке нужно создать массив, который будет состоять из объектов типа Exhibit, Picture, Sculpture, не используя векторов и шаблонов(template)
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
16.03.2020, 13:15 27
Цитата Сообщение от Eg0ra1 Посмотреть сообщение
В последней строчке нужно создать массив, который будет состоять из объектов типа Exhibit, Picture, Sculpture, не используя векторов и шаблонов(template)

Eg0ra1
,
Цитата Сообщение от IGPIGP Посмотреть сообщение
Однако ТС отказывается от шаблонных контейнеров и вы правы в том, что суть вопроса легко показать на простом. И это массив.
А суть в полиморфной природе объекта и если идти от "рекомендаций", то контейнер unique_ptr был бы хорош. Но новичку это не надо (по его заявлению).
Выделить блок памяти под указатели базового класса сможете?
Что делать дальше показал L0M, вот тут:
Как создать полиморфный массив?
0
0 / 0 / 0
Регистрация: 07.10.2019
Сообщений: 78
16.03.2020, 13:25  [ТС] 28
Неа
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
16.03.2020, 16:23 29
Цитата Сообщение от Eg0ra1 Посмотреть сообщение
Неа
Eg0ra1, раз контейнеров не нужно, то и слёз тоже. Где боевая раскраска и дикая бесстрашная песня? Нужно то всего: пробежать по файлу и посчитать объекты. Потом не закрывать, а выделить память под блок (динамический "массив" указателей). Снова пройти по файлу от начала и прочесть, создавая объекты в куче и перенося указатели в массив. Операторы ввода там какие-то есть. Хотя лучше бы сделать полиморфный метод вызываемый в операторе принимающем ссылку на базовый класс... Или ещё как-то, чтобы не повторять код в каждом операторе.
Eg0ra1, беда в том, что вам не массив полиморфных указателей нужен. Вам нужен массив тех, кто напишет вам программу.
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,284
16.03.2020, 16:36 30
Цитата Сообщение от Eg0ra1 Посмотреть сообщение
// полиморфный массив
Вот тут вам дали ответ на вопрос: Как перегрузить >> для записи в файл?
0
Мозгоправ
1744 / 1038 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
16.03.2020, 16:39 31
Цитата Сообщение от Eg0ra1 Посмотреть сообщение
1)Это разве не принцип создания матрицы, когда каждый элемент есть началом массива?Если да, тогда почему так?
Нет, это не массив массивов.
Смотрите #3, строка 32: A *arr[ARRLEN]; - здесь определяется массив указателей на базовый класс. Цикл (строки 34-40) - это инициализация этого массива: при каждом проходе цикла создаётся экземпляр одного из классов, который инициализируется переменной цикла. Здесь new A((int)i) в куче выделяется память для одного объекта, для которого вызывается конструктор с параметром типа int. Адрес этого объекта заносится в arr[i].

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

Кликните здесь для просмотра всего текста
Ошибки не будет ни при компиляции, ни в рантайме. Если метод не переопределён в дочернем классе, то будет вызван метод класса-родителя.
0
0 / 0 / 0
Регистрация: 07.10.2019
Сообщений: 78
16.03.2020, 17:12  [ТС] 32
Я не вы, чтобы просить написать мне программу)
0
Мозгоправ
1744 / 1038 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
16.03.2020, 17:45 33
Цитата Сообщение от IGPIGP Посмотреть сообщение
L0M, это необходимое но не достаточное условие, для массива - типа. <...> Но блок памяти в С++ массивом не является. Хотя называют его так частенько. И когда условность такого применения слову "массив" подразумевается, это допустимо. Однако в С++ есть 2 массива - C-style array и std::array<T>. Оба имеют размер времени компиляции.
Ну здесь я пытался донести до человека, что концепция массива настолько базовая, что если опуститься до железа, то голая оперативная память также является массивом минимально адресуемых областей памяти.

На счёт того, что "блок памяти в С++ массивом не является" - вопрос философский. В С++ "блок памяти" - это блок памяти, выделенный malloc() или др. подобной функцией (при выделении памяти по new типизация выполняется сразу). Т.е. после выделения памяти имеем указатель на void с адресом этого блока. Получается, что блок памяти становится массивом в тот момент, когда (1) мы кастим void* к указателю на тип, отличный от void и (2) мы подразумеваем, что данный указатель указывает не на единичный объект, а на несколько объектов, расположенных непрерывно в этом блоке памяти.

std::array<T> появился, если не ошибаюсь, только в С++11. До этого обходились и без него. Это скорее синтаксический сахар.
0
209 / 191 / 49
Регистрация: 15.03.2016
Сообщений: 1,211
16.03.2020, 17:49 34
Цитата Сообщение от L0M Посмотреть сообщение
Как вы сами понимаете, описанное выше - это совсем не std::vector (см. 26.3.11 Class template vector).
вот всё что вы там понаписали - это и есть демагогия. Куча букв про то, что "массив не вектор".
Запутывание терминами, манипуляция понятиями. А теперь ещё больше букв про то, что это не демагогия
Когда vector - всего-лишь набёр обёрток для работы с массивом. В основе у него массив. Работают там все функции с массивом. А всё что он делает:
- автоматизирует new/delete
- автоматизирует resize
- ловит и грамотно обрабатывает ошибки (так чтобы программа не падала)
- имеет функции поиска и прочие вспомогательные методы, упрощающие жизнь программисту
И всё это он делает с массивом!

Теперь, что такое массив, собственно...
Я так понимаю, термин map-to-hardware вам не знаком. Массив - это хранение данных напрямую в ячейках памяти.
В коде у вас {1,2,3}, а в реальности там ровно также заняты ячейки памяти под №№: 777,778,779 (утрировано).
Т.е. массив - это 1-к-1 отражение, как в памяти хранятся данные. И он не может быть каким-то иным в векторе или где-либо ещё. В C/C++ данные в памяти хранятся именно так и никак иначе - они просто занимают ячейки подряд и вы также напрямую с этими ячейками и работаете. Всегда.
А уж как вы с ними работаете - через vector, через array или прямо через [] - дело стодвадцатьпятое. Там всего-лишь доп.обёртки для работы со сгруппированными ячейками.

С демагогами одна проблема, они никогда не возьмут в толк, что сколько бы бумаги не исписали, а гранит истины поломать невозможно.
Истина всегда останется неизменной и, рано или поздно, все иллюзии убьются об этот гранит.
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
16.03.2020, 18:39 35
Цитата Сообщение от L0M Посмотреть сообщение
Получается, что блок памяти становится массивом в тот момент, когда (1) мы кастим void* к указателю на тип, отличный от void и (2) мы подразумеваем, что данный указатель указывает не на единичный объект, а на несколько объектов, расположенных непрерывно в этом блоке памяти.
L0M, это настолько же верно как и то, что указатель на любой блок можно скастить к чему угодно. Но массив это тип. Впрочем, ТС как раз нуждается именно в динамическом (так называемом) массиве. Но вопрос же не в этом. Если человек не знает как выделить память и отказывается от контейнеров, то вопрос откуда код. Там нужно всё переписывать, почти.
Цитата Сообщение от L0M Посмотреть сообщение
std::array<T> появился, если не ошибаюсь, только в С++11. До этого обходились и без него. Это скорее синтаксический сахар.
Это можно и так увидеть.
Цитата Сообщение от L0M Посмотреть сообщение
мы подразумеваем, что данный указатель указывает не на единичный объект, а на несколько объектов, расположенных непрерывно в этом блоке памяти.
Мы подразумеваем. Указателю всё едино. У него от природы оператор индексации вшит. Вообще, спор о массивах и указателях - скука.
Я вот не врубился ТС писатель или читатель? Там он открывает файл, а потом пытается из него читать? Потом закрывает и просит создать массив данных? Там всё нужно делать почти с нуля. Просто и не интересно.
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
16.03.2020, 20:32 36
Цитата Сообщение от полудух Посмотреть сообщение
А уж как вы с ними работаете - через vector, через array или прямо через [] - дело стодвадцатьпятое. Там всего-лишь доп.обёртки для работы со сгруппированными ячейками.
Именно об этом вам талдычили, а вы всё упирались и упирались.
0
Мозгоправ
1744 / 1038 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
16.03.2020, 21:44 37
Цитата Сообщение от полудух Посмотреть сообщение
С демагогами одна проблема, они никогда не возьмут в толк, что сколько бы бумаги не исписали, а гранит истины поломать невозможно.
Истина всегда останется неизменной и, рано или поздно, все иллюзии убьются об этот гранит.
М-да... Зря я клавиатуру топтал в стремлении что-то вам объяснить. Вы просто банальный тролль.
1
16.03.2020, 21:44
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.03.2020, 21:44
Помогаю со студенческими работами здесь

Если можно создать массив TButton, то как создать массив их событий?
Пишу программу в которой много однообразных Едитов и кнопок. Чтобы &quot;облегчить сбе жизнь&quot; создал...

Полиморфный метод
Здравствуйте! Мне необходимо в иерархии наследования реализовать полиморфный метод. Создать...

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

Полиморфный конструктор [C++]
Добрый день форумчане! Помогите разобраться, что такое полиморфный конструктор. На рсдн нашел про...


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

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