Страницы

Поиск по вопросам

вторник, 17 марта 2020 г.

Массив из разных типов [дубликат]

#массивы #хранилище #cpp


        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Можно ли хранить объекты разных классов (производных
одного абстрактного класса) в одном массиве или списке?
                                
                                    (3 ответа)
                                
                        
                                Закрыт 2 года назад.
            
                    
Существует ли возможность в c++ сделать массив из разных типов? Или какое-то хранилище-переменную,
в которой можно хранить разнотиповые вещи? У меня есть несколько структур, и массив,
который будет динамически изменяться, и вот хотелось бы как-то добавлять в него значения
разных типов.    


Ответы

Ответ 1



Предложу ещё третий, более с++ способ. Какие разрообразные объекты у Вас не были бы, все равно у них есть общий предок (да, void* - это вырожденный случай и обычно говорит либо о сильной преждевременной оптимизации или просто незнания ООП). Итак, первое - нужно написать базовый класс. От него наследуются другие классы для разных данных. Даже если нужно хранить строку и число. Так как есть базовый класс, то можно написать std::vector vec; и уже есть массив объектов. Пусть нужно вывести всех их на печать. Для этого для каждого наследника нужно определить метод вида friend ostream& operator<<(ostream& os, const YourType& dt); И все, можно будет выводить на печать таким кодом for (int i = 0; i < vec.size(); i++) std::cout << vec[i] << std::endl; Очень просто. Но пусть нужно сохранять объекты и загружать с файла. Добавим в базовый тип виртуальный метод "getObjectType", "getObjectSize", "saveToStream" и "loadFromStream". Каждый наследник должен будет их определить. Теперь при сохранении где то так fstream fs; fs.write(vec.size(), sizeof(size_type)); for (int i = 0; i < vec.size(); i++) { int t = vec[i].getObjectType(); size_t s = vec[i].getObjectSize(); fs.write(t, sizeof(t)); fs.write(s, sizeof(s)); vec[i].writeToStream(fs); } красиво? А вот с загрузкой немного сложнее. Нужно будет хранить массив соответствий "тип объекта"->"ссылка на конструктор". Но при небольшом кол-ве объектов, можно и if-else или switch size_type c; fs.read(c, sizeof(c)); for (int i = 0; i < c; i++) { int t; size_t s; BaseObj* bb; fs.read(t, sizeof(t)); fs.read(s, sizeof(s)); switch (t) { case 1: bb = new IntObject(); break; case 2: bb = new StringObject(); break; //.... default: // unknown object, can skip fs.seekg (s, fs.beg); break; } bb->loadFromStream(fs, s); } upd Главное не забывать делать методы виртуальными, а также сделать виртуальным деструктор. Конечно, если классы не будут иметь общего предка, то все это работать не будет.

Ответ 2



да такое можно сделать, но если вам это понадобилось то скорее всего имеет смысл переделать архитектуру программы. реализовать это можно например в виде велосипеда над указателями Void. или гораздо лучший вариант это использовать boost boost::Any вот тут можно почитать в любом случае, лучше сначала подумать над архитектурой. UPD собственно пример изменения архитектуры привёл KoVadim...

Комментариев нет:

Отправить комментарий