Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19

Динамически созданные классы

25.03.2021, 19:04. Показов 2697. Ответов 20

Студворк — интернет-сервис помощи студентам
Привет. Имеются 2 класса: Album, содержащий альбом(-ы) группы, в который также включен другой класс Song, где хранятся песни из этого альбома. Так выглядит их структура:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Album
{
private:
    std::string Name; // имя альбома
    int ReleaseYear; // год выпуска
    Song* Songs; // указатель на массив песен
};
 
class Song
{
private:
    std::string Name; // имя песни
    int Duration; // длительность
    Genre SongGenre; // жанр песни
};
И есть функция, которая запрашивает инфу у пользователя о 3 альбомах, в каждом из которых по 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
26
27
28
29
30
31
32
33
34
35
36
const int r = 3;
const int songNum = 4;
Album* alb = new Album[r]; // создаем массив альбомов в кол-ве 3 штук
 
std::string s;
int b = 0;
 
for (int i = 0; i < r; ++i)
    {
        std::cout << "\nEnter " << i + 1 << " album name: ";
        std::getline(std::cin, s);
 
        alb[i].SetAlbumName(s); // устанавливаем имя альбома [i]
        std::cin.sync();
 
        std::cout << "\nEnter album release year: ";
        CheckForNumber(b); // эта функция проверяяет введенную строку только на числа
        alb[i].SetAlbumReleaseYear(b); 
 
        Song* son = new Song[songNum] { }; // выделяем память под массив песен
        std::cout << "\nEnter 4 songs to be placed in this album: ";
 
        for (int g = 0; g < songNum; ++g)
        {
            std::cout << "Song #" << g + 1 << ": ";
            std::getline(std::cin, s);
 
            son[g].SetSongName(s); // задаем песне [g] имя
            std::cin.sync();
 
        }
 
        alb[i].SetAlbumSongs(son); // после цикла заносим в альбом [i] указатель на песни son
 
        delete[] son; // удаляем массив песен; для нового альбома будет создан новый массив песен
    }
Цикл работает, однако как только мы удаляем массив песен в последней строчке, почему-то затираются и данные о песне, которые были занесены в альбом. Но есть одно но - если код изменить на этот:

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
const int r = 3;
const int songNum = 4;
Album* alb = new Album[r]; 
 
std::string s;
int b = 0;
int c = 0;
 
Song* TestSong = new Song[10] { }; // создаем массив вне цикла
 
for (int i = 0; i < r; ++i)
    {
        std::cout << "\nEnter " << i + 1 << " album name: ";
        std::getline(std::cin, s);
 
        alb[i].SetAlbumName(s); 
        std::cin.sync();
 
        std::cout << "\nEnter album release year: ";
        CheckForNumber(b); 
        alb[i].SetAlbumReleaseYear(b); 
 
        Song* son = new Song[songNum] { }; 
        std::cout << "\nEnter 4 songs to be placed in this album: ";
 
        c = 0;
        for (int g = 0; g < songNum; ++g)
        {
            std::cout << "Song #" << g + 1 << ": ";
            std::getline(std::cin, s);
 
            son[g].SetSongName(s); 
            std::cin.sync();
                        
            TestSong[c] = son[g]; // тут уже переношу песни из son в TestSong, чтобы не удалялись данные после
            ++c;                          // очистки памяти 
        }
 
        alb[i].SetAlbumSongs(TestSong); 
 
        delete[] son;
    }
То всегда в alb сохраняются только песни, созданные в третьем альбоме (т.е. последнем). Есть какие-нибудь идеи?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.03.2021, 19:04
Ответы с готовыми решениями:

Классы. Объявить массив динамически и сделать указатель на объект в динамической памяти
Я создал классы: ПЕРСОНА, служащий, роботодатель, инженер. Но мне нужно в программе (после int main() 69 строка) объявить массив...

Динамически созданные кнопки
Проектирую класс для отображения графиков. Всё устройст делиться на три части: 1 класс MGraphView унаследованыый от QMainWindow,2 класс...

Динамически созданные компоненты
Вопрос такого характера, когда я создаю на форме динамически компоненты, пример в данном примере создаю по родителю перенесенного на...

20
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12919 / 6787 / 1817
Регистрация: 18.10.2014
Сообщений: 17,169
25.03.2021, 19:54
Лучший ответ Сообщение было отмечено Skel как решение

Решение

Цитата Сообщение от Skel Посмотреть сообщение
C++
1
2
alb[i].SetAlbumSongs(son); // после цикла заносим в альбом [i] указатель на песни son
delete[] son; // удаляем массив песен; для нового альбома будет создан новый массив песен
Так а где определение метода SetAlbumSongs? Почему оно не приведено в вашем вопросе? Как мы должны догадаться, что этот метод делает?

Запоминает указатель на массив? Так вы же потом сразу уничтожаете этот массив. Как это должно работать, по-вашему?
0
Гвоздь Задиров
 Аватар для Folian
1718 / 1117 / 337
Регистрация: 25.01.2019
Сообщений: 2,940
25.03.2021, 20:00
Цитата Сообщение от Skel Посмотреть сообщение
есть функция, которая запрашивает инфу
Что она возвращает/принимает?

Цитата Сообщение от Skel Посмотреть сообщение
как только мы удаляем массив песен в последней строчке, почему-то затираются и данные о песне, которые были занесены в альбом.
А зачем ты их удаляешь-то?
Цитата Сообщение от Skel Посмотреть сообщение
Есть какие-нибудь идеи?
Работай с памятью аккуратнее.
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12919 / 6787 / 1817
Регистрация: 18.10.2014
Сообщений: 17,169
25.03.2021, 20:01
Цитата Сообщение от Skel Посмотреть сообщение
То всегда в alb сохраняются только песни, созданные в третьем альбоме (т.е. последнем). Есть какие-нибудь идеи?
Ым... Но вы же сами сделали так, чтобы все альбомы указывали на один и тот же массив песен TestSong. Разумеется, во всех альбомах будут одни и те же песни - какие песни последними записались в TestSong, те и будут. Почему вас это удивляет?
1
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
25.03.2021, 20:59  [ТС]
C++
1
2
3
4
void SetAlbumSongs(Song* songs)
    {
        this->Songs = songs;
    }
Просто передается указатель на песни
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12919 / 6787 / 1817
Регистрация: 18.10.2014
Сообщений: 17,169
25.03.2021, 21:03
Цитата Сообщение от Skel Посмотреть сообщение
Просто передается указатель на песни
Ну так... См. выше.
0
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
25.03.2021, 21:06  [ТС]
Это void-функция. Она просто запрашивает данные для альбомов и песен и заполняет эти данные, на вход ничего, она все внутри себя создает;

Я уже понял, что удалять было глупой идеей, поэтому тот массив son стал как бы временным. Из него я копирую 4 песни для первого альбома в TestSong, затем этот TestSong передаю альбому 1. И так далее все 3 альбома;

Аккуратнее с памятью работать в каком смысле? Если ты про проверки на то, удаляются ли массивы потом, то это не проблема, я предусмотрел.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12919 / 6787 / 1817
Регистрация: 18.10.2014
Сообщений: 17,169
25.03.2021, 21:11
Цитата Сообщение от Skel Посмотреть сообщение
Я уже понял, что удалять было глупой идеей, поэтому тот массив son стал как бы временным. Из него я копирую 4 песни для первого альбома в TestSong,
Зачем что-то куда-то копировать? Почему бы просто не убрать удаление?

Цитата Сообщение от Skel Посмотреть сообщение
Из него я копирую 4 песни для первого альбома в TestSong, затем этот TestSong передаю альбому 1. И так далее все 3 альбома;
Именно. Во все три альбома вы передаете один и тот же массив TestSong.
0
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
25.03.2021, 21:13  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Но вы же сами сделали так, чтобы все альбомы указывали на один и тот же массив песен TestSong
Почему? Я ведь каждому отдельному альбому свой массив TestSong передаю.
C++
1
alb[i].SetAlbumSongs(TestSong);
При увеличении i сбрасывается счетчик c (int c = 0), и в массив TestSong заново начинают записываться новые значения для нового альбома. По-моему все нормально, старые данные, что были в этом TestSong, просто затираются новыми
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12919 / 6787 / 1817
Регистрация: 18.10.2014
Сообщений: 17,169
25.03.2021, 21:15
Цитата Сообщение от Skel Посмотреть сообщение
Я ведь каждому отдельному альбому свой массив TestSong передаю.
О чем вы? Вы в своей программе создали один-единственный массив TestSong - в строке 9. Вот этот один-единственный массив вы передаете во все альбомы. Откуда тут мог взяться "каждому отдельному альбому свой"???

Покажите мне пальцем, где вы в своей программе создаете "каждому отдельному альбому свой".
0
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
25.03.2021, 21:16  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Почему бы просто не убрать удаление?
Хм, имеешь в виду вообще son не удалять? Память же утечет, т.к. вне цикла я уже к нему доступ не получу, не?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12919 / 6787 / 1817
Регистрация: 18.10.2014
Сообщений: 17,169
25.03.2021, 21:22
Цитата Сообщение от Skel Посмотреть сообщение
и в массив TestSong заново начинают записываться новые значения для нового альбома. По-моему все нормально, старые данные, что были в этом TestSong, просто затираются новыми
Вот именно. Как вы сами сказали: "затираются новыми". Вы на этот массив TestSong уже ссылаетесь из предыдущего альбома. И вы при обработке нового альбома затираете данные в этом массиве. В результате все данные предыдущего альбома затираются. Что тут непонятного?

Массив TestSong у вас один на все альбомы. Какие данные вы в него запишете последними - такие и будут видны изо всех альбомов. Именно это вы и наблюдаете.

Добавлено через 4 минуты
Цитата Сообщение от Skel Посмотреть сообщение
Хм, имеешь в виду вообще son не удалять? Память же утечет, т.к. вне цикла я уже к нему доступ не получу, не?
Как это "утечет"? У вас же в альбомах будет храниться указатель Song* Songs; именно на этот массив. Пока этот указатель хранится в альбомах, доступ к массиву у вас не потерян и память не является утекшей.
1
Гвоздь Задиров
 Аватар для Folian
1718 / 1117 / 337
Регистрация: 25.01.2019
Сообщений: 2,940
25.03.2021, 21:25
Skel, Короче, вот пример без лишней мишуры:
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
#include <iostream>
 
class B
{
public:
    int data;
};
 
class A
{
public:
    B* b;
};
 
A* foo(int a_size, int b_size)
{
    A* pA = new A[a_size];
 
    for(int i = 0; i < a_size; ++i)
    {
        B* pB = new B[b_size];
 
        for(int j = 0; j < b_size; ++j)
        {
            std::cout << "A[" << i << "].b[" << j << "] :";
            std::cin >> pB[j].data;
        }
        pA[i].b = pB;
    }
 
    return pA;
}
 
int main()
{
    int a_size = 2;
    int b_size = 3;
 
    A* p = foo(a_size, b_size);
 
    for(int i = 0; i < a_size; ++i)
    {
        for(int j = 0; j < b_size; ++j)
        {
            std::cout << "\n" << "A[" << i << "].b[" << j << "] :" << p[i].b[j].data;
        }
    }
 
    for(int i = 0; i < a_size; ++i)
        delete[] p[i].b; // эту штуку лучше воткнуть в деструктор А с проверкой; тут лишь для наглядности места освобождения
                    // и выделять лучше через метод в A, чтоб вышло что-то около закомментированного ниже
                    // ну это как мне видится, может лучше иначе
    delete [] p;
 
 
    system("pause");
    return 0;
}
 
/*
class A
{
public:
    B* b;
    A() : b(nullptr) {}
    ~A()
    {
        if (b != nullptr) delete [] b;
    }
 
    void new_b(size_t size)
    {
        if (b != nullptr) delete [] b;
        b = new B[size];
    }
};*/
1
Модератор
Эксперт CЭксперт С++
 Аватар для Volga_
5208 / 2925 / 1509
Регистрация: 14.12.2018
Сообщений: 5,266
Записей в блоге: 1
25.03.2021, 21:32
Del/////
1
Гвоздь Задиров
 Аватар для Folian
1718 / 1117 / 337
Регистрация: 25.01.2019
Сообщений: 2,940
25.03.2021, 21:35
Цитата Сообщение от Volga_ Посмотреть сообщение
По-моему мы должны вставить delete [] p->b внутри цикла for(int i = 0; i < a_size; ++i) !
Такой:
Не совсем, я уже исправил.
Цитата Сообщение от Volga_ Посмотреть сообщение
delete [] p->b внутри цикла
приведёт к многократному delete [] p[0].b . Индекс нужен p[i]
1
Модератор
Эксперт CЭксперт С++
 Аватар для Volga_
5208 / 2925 / 1509
Регистрация: 14.12.2018
Сообщений: 5,266
Записей в блоге: 1
25.03.2021, 21:39
Цитата Сообщение от Folian Посмотреть сообщение
приведёт к многократному delete [] p[0].b . Индекс нужен p[i]
Понял. Очень жаль я думал, что мне не правильно и удалил свой пост перед того, как вы ответили на его.
1
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
25.03.2021, 21:40  [ТС]
Точно, а ведь просто не надо было удалять эти массивы. Просто я привык при выделении чего-либо динамического сразу где-нибудь его удаление делать. Спасибо за ответы
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12919 / 6787 / 1817
Регистрация: 18.10.2014
Сообщений: 17,169
25.03.2021, 21:51
Цитата Сообщение от Skel Посмотреть сообщение
Просто я привык при выделении чего-либо динамического сразу где-нибудь его удаление делать.
Сделать можно по-разному. Эта тема называется resource ownership - владение ресурсами. Кто является владельцем ("хозяином") выделенной памяти - тот и удалять ее обязан, когда она становится ненужной. И совсем не обязательно "сразу".

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

C++
1
alb[i].SetAlbumSongs(son);
вы передаете право владения массивом son альбому alb[i]. После этого вы уже не должны "сразу" освобождать массив son. Это alb[i] будет освобождать эту память тогда, когда придет время.

---

Вот для того, чтобы не переусложнять эту тему, и придуманы контейнеры и/или умные указатели. Которым вы в своем коде почему-то не пользуетесь.
2
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
25.03.2021, 21:53  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Для того, чтобы не переусложнять эту тему, и придуманы контейнеры и умные указатели. Которым вы в своем коде почему-то не пользуетесь.
Потому что я еще не дотрагивался до этой темы. Не в первый раз слышу, что эти контейнеры все хвалят
0
Гвоздь Задиров
 Аватар для Folian
1718 / 1117 / 337
Регистрация: 25.01.2019
Сообщений: 2,940
25.03.2021, 22:35
Цитата Сообщение от Skel Посмотреть сообщение
Не в первый раз слышу, что эти контейнеры все хвалят
О, они прекрасны.

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
/*например*/
#include <iostream>
#include <vector>
#include <string>
 
class Album
{
public:
    std::string name;
    std::vector<std::string> songs;
 
    void show()
    {
        std::cout << "\n\n" << name;
        for(auto i : songs) std::cout << "\n\t" << i;
    }
};
 
typedef std::vector<Album> vAlbums;
 
void add_data(vAlbums& albums)
{
    std::string new_album;
    std::cout << "New album:";
    std::getline(std::cin, new_album);
 
    while(!new_album.empty())
    {
        albums.push_back(Album());
        albums.back().name = new_album;
 
 
        std::string new_song;
        std::cout << "new song:";
        std::getline(std::cin, new_song);
        while (!new_song.empty())
        {
            albums.back().songs.push_back(new_song);
            std::cout << "new song:";
            std::getline(std::cin, new_song);
        }
 
        std::cout << "New album:";
        std::getline(std::cin, new_album);
    }
}
 
int main()
{
    vAlbums Al;
    add_data(Al);
 
    for(auto i : Al) i.show();
 
    system("pause");
    return 0;
}
Цитата Сообщение от Skel Посмотреть сообщение
я еще не дотрагивался до этой темы
ну std::string-то потрогал?
Миниатюры
Динамически созданные классы  
Изображения
 
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.03.2021, 22:35
Помогаю со студенческими работами здесь

Динамически созданные кнопки
Я создал 5 кнопок. А как при нажатии на кнопку узнать ее индекс? TButton *array_btn; for(int i = 0; i &lt; 5; i++) { ...

Как удалять динамически созданные компоненты?
Хедер #include &lt;Math.hpp&gt; #include &lt;math.h&gt; #include &lt;vcl.h&gt; #include &quot;PressedMatch.h&quot; class Client { AnsiString fio; ...

Динамически созданные компоненты ведут себя так, будто их высота больше, чем есть
Всем доброго здравия :) Проблемка из области &quot;истина где-то рядом&quot;... Динамически создаю компоненты VLC TImage и TLabel,...

Динамически созданные компоненты
я создаю компоненты по нажатию на кнопку TextBox tx = new TextBox(); tx.Name = &quot;razdel&quot; +...

Динамически созданные обьекты?
Всем привет, кто знает подскажите!!! В коде динамически создаю кнопки на экране, как везде написано, доступ к таким элементам можно...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru