Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/41: Рейтинг темы: голосов - 41, средняя оценка - 4.73
 Аватар для Gr1f0nn
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690

Как хранить объекты разных классов в одном контейнере

23.10.2014, 18:29. Показов 8235. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте!

Хочу реализовать хранение разных классов(базовый и наследник) в одном контейнере. На форуме искал, но, к сожалению, не нашел ответа на свой вопрос. Понял только то, что я должен хранить указатели на объекты классов.
Что я попробовал сделать:

Классы:
Кликните здесь для просмотра всего текста
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 info
{
protected:
    string message;
public:
    info();
    info(string _message);
    ~info();
    void set_message(string _message);
    virtual string get_message();
    friend class Dialog;
};
 
class infoD : public info
{
private:
    string nick;
public:
    infoD();
    infoD(string _message, string _nick);
    ~infoD();
    void set_name(string _message, string _nick);
    virtual string get_message();
    friend class Dialog;
};


Реализация методов:
Кликните здесь для просмотра всего текста
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
info::info()
{
    message = "";
}
 
info::info(string _message)
{
    message = _message;
}
 
info::~info()
{
 
}
 
void info::set_message(string _message)
{
    message = _message;
}
 
string info::get_message()
{
    return string("Message: ") + message;
}
 
infoD::infoD() : info()
{
    nick = "";
}
 
infoD::infoD(string _message, string _nick) : info(_message)
{
    nick = _nick;
}
 
infoD::~infoD()
{
 
}
 
void infoD::set_name(string _message, string _nick)
{
    nick = _nick;
    set_message(_message);
}
 
string infoD::get_message()
{
    return string("Message: ") + message + string("Name: ") + nick;
}


Хранение:
Кликните здесь для просмотра всего текста
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
static list<info> ob;
void Dialog::on_addLast_clicked()
{
    string data, name;
    if(ui->type->currentText() == "Message")
    {
        if(ui->messageLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            ob.push_back(info(data));
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->deleteCurr->show();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
    if(ui->type->currentText() == "Message + name")
    {
        if(ui->messageLine->text() != "" && ui->nameLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            name = ui->nameLine->text().toStdString();
            ob.push_back(infoD(data,name));
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->nameLine->setText("");
            ui->deleteCurr->show();
        }
    }
}


Вывод:

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Dialog::on_show_clicked()
{
    if(ob.empty())
    {
        ui->console->clear();
        QMessageBox::warning(this,"Information","List empty!",QMessageBox::Ok);
    }
    else
    {
        ui->console->clear();
        list<info>::iterator el = ob.begin();
        do
        {
            QString msg = QString::fromStdString(el->get_message());
            ui->console->addItem(msg);
            el++;
        }
        while(el != ob.end());
    }
}


Т.е. у меня есть виртуальный метод get_message(), следовательно, когда я обращаюсь к объекту через указатель, компилятор должен сам выбрать, какой из методов вызвать. Он же вызывает всегда метод базового класса

До этого сохранял объекты в контейнер так:
C++
1
2
p = new info(data)
ob.push_back(*p)
Тоже не работало.

Пробовал еще делать так:
C++
1
list<info*> ob;
Также не помогло.


Заранее спасибо за помощь!
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
23.10.2014, 18:29
Ответы с готовыми решениями:

Объекты разных типов в одном контейнере и c++ 11 auto
Собственно дабы упростить себе жизнь, решил использовать auto но столкнулся с траблом... class TWireObj{ public: TWireObj(auto...

Как сделать хитрое наследование? Хранить в одном контейнере родителя и потомков
Доброго времени суток! Интересует, можно ли при создании класса-потомка назначать его родительский класс (не копировать, а именно...

В каком STL-контейнере лучше хранить объекты?
Есть класс, реализующий адреса class address { ... } Поискал в сети увидел 3 варианта хранения объектов : массив(array),...

4
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
23.10.2014, 18:36
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
На форуме искал, но, к сожалению, не нашел ответа на свой вопрос.
Внизу страницы есть блок "Похожие темы", в котором целая пачка тем с аналогичными вопросами.
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Также не помогло.
Вариант с хранением указателя на базовый класс - рабочий. Как понимать "не помогло"?
0
 Аватар для Gr1f0nn
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
23.10.2014, 18:43  [ТС]
Цитата Сообщение от 0x10 Посмотреть сообщение
Внизу страницы есть блок "Похожие темы", в котором целая пачка тем с аналогичными вопросами.
Я бы не задавал вопрос, если бы нашел на него ответ

Цитата Сообщение от 0x10 Посмотреть сообщение
Вариант с хранением указателя на базовый класс - рабочий. Как понимать "не помогло"?
Не получается потом работать с итераторами.
Например:
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
static list<info*> ob;
void Dialog::on_addLast_clicked()
{
    string data, name;
    info *p;
    if(ui->type->currentText() == "Message")
    {
        if(ui->messageLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            p = new info(data);
            ob.push_back(p);
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->deleteCurr->show();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
    if(ui->type->currentText() == "Message + name")
    {
        if(ui->messageLine->text() != "" && ui->nameLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            name = ui->nameLine->text().toStdString();
            p = new infoD(data,name);
            ob.push_back(p);
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->nameLine->setText("");
            ui->deleteCurr->show();
        }
    }
}
Вызов функции вывода:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Dialog::on_show_clicked()
{
    if(ob.empty())
    {
        ui->console->clear();
        QMessageBox::warning(this,"Information","List empty!",QMessageBox::Ok);
    }
    else
    {
        ui->console->clear();
        list<info*>::iterator el = ob.begin();
        do
        {
            QString msg = QString::fromStdString(el->get_message());
            ui->console->addItem(msg);
            el++;
        }
        while(el != ob.end());
    }
}


Ошибки:
D:\WorkC\GUIver3-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK_________\..\GUIver3\dialo g.cpp:119: ошибка: request for member 'get_message' in '* el.std::_List_iterator<_Tp>::operator-> [with _Tp = info*]()', which is of non-class type 'info*'
0
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
23.10.2014, 18:45
Лучший ответ Сообщение было отмечено Gr1f0nn как решение

Решение

Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Не получается потом работать с итераторами.
А это уже совсем другая проблема.
Если
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
list<info*>::iterator el = ob.begin();
тогда ниже:
C++ (Qt)
1
QString msg = QString::fromStdString((*el)->get_message());
1
 Аватар для Gr1f0nn
244 / 164 / 133
Регистрация: 30.09.2012
Сообщений: 690
23.10.2014, 18:49  [ТС]
0x10, Оно заработало!
Большое спасибо!

Не по теме:

Про скобочки-то я и забыл

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.10.2014, 18:49
Помогаю со студенческими работами здесь

Хранение в контейнере обьектов разных классов
Здраствуйте. Есть небольшая иерархия классов, в вершине которой стоит абстрактный класс vehicle, а от него наследуеться пару классов....

Как приравнять объекты двух разных классов
написал свой класс Angle(угол). А теперь нужно сделать так Angle c; Label1-&gt;Caption=c; Знаю, что нужно как-то по колдовать) Но как?

Сложить объекты двух разных классов
Здравствуйте, при изучении программирования всплыл такой вопрос. Без объявления базового класса, возможно ли сложить 2 их объекта? И как...

Как корректно особождать объекты в контейнере
Всё ли так я делаю? template &lt;typename T&gt; class TArray : public FArray { ~TArray() { if constexpr...

Есть ли способ хранить массив классов без инициализации (хранить только их заголовки)?
Есть ли способ хранить массив классов без инициализации, а только их заголовки и в нужный момент достать их с массива и инициализировать?


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru