С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/34: Рейтинг темы: голосов - 34, средняя оценка - 5.00
16 / 11 / 6
Регистрация: 18.07.2018
Сообщений: 51
1

Динамический массив при наследовании, элементами которого являются объекты класса наследника динамический массив

22.07.2018, 11:34. Показов 6366. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Попробовал создать динамический массив, у которого элементы - объекты класса динамический массив, причем использовал класс-наследник от базового, при создании объекта вызывается деструктор и данные стираются, видел такое с указателями, но такого не нашел
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include<iostream>
#include<ctime>
 
using namespace std;
 
class First
{
public:
    First()
    {
        this->size = 3;
        arr = new int[size];
        for (int i = 0; i < size; i++)
        {
            arr[i] = 0;
        }
        cout << "Вызвался конструктор по-умолчанию First" << endl;
    }
 
    First(int size)
    {
        this->size = size;
        this->arr = new int[size];
        for (int i = 0; i < size; i++)
        {
            arr[i] = rand() % 10;
        }
        cout << "Вызвался конструктор с параметрами First" << endl;
    }
 
    void Print()
    {
        for (int i = 0; i < this->size; i++)
        {
            cout << arr[i] << "\t";
        }
        cout << endl;
    }
 
    First(const First & second)
    {
        this->size = second.size;
        this->arr = new int[second.size];
        for (int i = 0; i < second.size; i++)
        {
            this->arr[i] = second.arr[i];
        }
        cout << "Вызвался конструктор копирования First" << endl;
    }
 
    First& operator=(const First& second)
    {
        if (this != &second)
        {
            delete[] this->arr;
            this->size = second.size;
            this->arr = new int[second.size];
            for (int i = 0; i < second.size; i++)
            {
                this->arr[i] = second.arr[i];
            }
        }
        cout << "Вызвался оператор присвоения First" << endl;
        return *this;
    }
 
    First(First &&second)
    {
        moveImpl(forward<First>(second));
        cout << "Вызвался конструктор перемещения" << endl;
    }
 
    virtual~First()
    {
        cout << "Вызвался деструктор класса First" << endl;
        delete[]arr;
    }
 
protected:
    void moveImpl(First &&rhs)
    {
        swap(size, rhs.size);
        swap(arr, rhs.arr);
    }
    int size;
    int *arr;
};
 
class Second :public First
{
public:
    Second() :First()
    {
        this->size = 3;
        arr = new int[size];
        for (int i = 0; i < size; i++)
        {
            arr[i] = 100;
        }
        cout << "Вызвался констуктор по-умолчанию класса Second" << endl;
    }
 
    Second(int size) :First(size)
    {
        this->size = size;
        this->arr = new int[size];
        for (int i = 0; i < size; i++)
        {
            arr[i] = rand() % 10;
        }
        cout << "Вызвался констуктор класса Second" << endl;
    }
 
    Second(const Second & second)
    {
        this->size = second.size;
        this->arr = new int[second.size];
        for (int i = 0; i < second.size; i++)
        {
            this->arr[i] = second.arr[i];
        }
        cout << "Вызвался конструктор копирования Second" << endl;
    }
 
    Second(Second &&second)
    {
        moveImpl(forward<Second>(second));
        cout << "Вызвался конструктор перемещения" << endl;
    }
 
    Second & operator=(const Second& second)
    {
        if (this != &second)
        {
            delete[] this->arr;
            this->size = second.size;
            this->arr = new int[second.size];
            for (int i = 0; i < second.size; i++)
            {
                this->arr[i] = second.arr[i];
            }
        }
        cout << "Вызвался оператор присвоения Second" << endl;
        return *this;
    }
 
    ~Second()override
    {
        delete[]arr;
        cout << "Вызвался дестуктор класса Second" << endl;
    }
 
private:
    void moveImpl(Second &&rhs)
    {
        swap(size, rhs.size);
        swap(arr, rhs.arr);
    }
    int size;
    int *arr;
};
 
 
int main()
{
    system("chcp 1251 >>null");
    srand(time(NULL));
    int size = 3;
    First *arr = new Second[size];
    for (int i = 0; i < size; i++)
    {
        arr[i] = Second(10);
    }
    for (int i = 0; i < size; i++)
    {
        arr[i].Print();
    }
 
    delete[]arr;
 
    return 0;
}
Причем ,если использовать такую запись ,то все работает
C++
1
2
3
4
5
6
7
8
9
10
11
12
int size = 3;
    First *arr = new First [size];
    for (int i = 0; i < size; i++)
    {
        arr[i] = Second(10);
    }
    for (int i = 0; i < size; i++)
    {
        arr[i].Print();
    }
 
    delete[]arr;
Не понимаю, что не так, понатыкал всего и не работает, заранее спасибо
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.07.2018, 11:34
Ответы с готовыми решениями:

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

Динамический массив указателей на объекты класса
Добрый вечер! Нужна помощь У меня имеется класс STROKA(вроде уже готовый,и все хорошо) Только...

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

Как создать одномерный динамический массив, элементами которого будут одномерные массивы разной длины?
Здравствуйте. Подскажите как создать одномерный динамический массив, элементами которого будут...

10
7803 / 6567 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
22.07.2018, 11:46 2
Зачем ты поля продублировал? Они и так наследуются.
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
22.07.2018, 13:17 3
Mikelyndgelo, это не хорошо:
Цитата Сообщение от Mikelyndgelo Посмотреть сообщение
First *arr = new Second[size];
Потому что освобождая:
delete[]arr;
вы вызываете деструктор базового класса так, что он будет вызван неверно при освобождении такого динамического массива. Фактически, массив наследников даже больше по размерам, чем массив объектов базового класса. Да и запуск базовых деструкторов в невиртуальном режиме (на объектах а не указателях наследника) не должен пройти бесследно. Для корректного удаления (если вы хотите вручную), нужно создать массив указателей на базовый класс. А при удалении - вручную проделитить каждый указатель. После чего вызвать общий делит для всего массива указателей. Я давно не делал ничего подобного руками и пишу по старой памяти. Если соврал, - пусть меня поправят.
1
16 / 11 / 6
Регистрация: 18.07.2018
Сообщений: 51
22.07.2018, 22:28  [ТС] 4
Цитата Сообщение от IGPIGP Посмотреть сообщение
Mikelyndgelo, это не хорошо:

Потому что освобождая:
delete[]arr;
вы вызываете деструктор базового класса так, что он будет вызван неверно при освобождении такого динамического массива. Фактически, массив наследников даже больше по размерам, чем массив объектов базового класса. Да и запуск базовых деструкторов в невиртуальном режиме (на объектах а не указателях наследника) не должен пройти бесследно. Для корректного удаления (если вы хотите вручную), нужно создать массив указателей на базовый класс. А при удалении - вручную проделитить каждый указатель. После чего вызвать общий делит для всего массива указателей. Я давно не делал ничего подобного руками и пишу по старой памяти. Если соврал, - пусть меня поправят.
Не очень понял, виртуальный деструктор я использовал, в каком порядке они вызываются я знаю, а что значит вручную, вы имеете ввиду, как мы удаляем двумерный динамический массив или что ,извиняюсь, если вопрос глупый, программированием занимаюсь сам и только 3 месяца, кстати как по-вашему мнению написан код в плане читаемости?
0
зомбяк
1584 / 1218 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
22.07.2018, 22:44 5
C++
1
2
3
4
Second() :First()
    {
        this->size = 3;
        arr = new int[size];
утечка памяти
C++
1
2
3
4
    Second(int size) :First(size)
    {
        this->size = size;
        this->arr = new int[size];
утечка памяти
C++
1
2
3
4
    Second(const Second & second)
    {
        this->size = second.size;
        this->arr = new int[second.size];
утечка памяти
Нужно очищать arr после конструктора First.

C++
1
this->
можно не писать (хотя когда сам был начинающим, тоже такое указывал)
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
22.07.2018, 22:50 6
Цитата Сообщение от Mikelyndgelo Посмотреть сообщение
Не очень понял, виртуальный деструктор я использовал, в каком порядке они вызываются я знаю
Виртуальные методы работают при вызове через указатель на базовый класс. Однако динамический массив удаляется оператором delete[] на указателе на начало выделенной памяти запуская деструкторы базового класса на объектах которые delete[] будет искать в массиве. Это совсем не тот случай когда деструкторы запускаются на указателях, понимаете?
Для начала, оставьте полиморфное наследование. Оставьте любое. Напишите класс в котором деструктор пишет на экран что-то вроде "I am destuctor". Создайте динамический массив. Удалите его delete[]. Подумайте о том что происходит. Почитайте.
А потом возвращаясь к наследованию (полиморфному) задумайтесь о том зачем оно нужно. Наследники имеют разные с базовым классом размеры, - больше обычно и разные между собой также. Они не могут вперемежку размещаться в одном массиве. Но профит от полиморфного поведения именно в возможности вызывать метод на коллекции гарантируя его полиморфное выполнение. Единственный выход, это массив указателей на базовый класс. Где уже сами указатели (объекты массива) указывают на разные полиморфные объекты. Это совсем не то, что Вы сделали инициализировав указатель базового класса массивом объектов наследника.
0
16 / 11 / 6
Регистрация: 18.07.2018
Сообщений: 51
22.07.2018, 23:03  [ТС] 7
Цитата Сообщение от IGPIGP Посмотреть сообщение
Виртуальные методы работают при вызове через указатель на базовый класс. Однако динамический массив удаляется оператором delete[] на указателе на начало выделенной памяти запуская деструкторы базового класса на объектах которые delete[] будет искать в массиве. Это совсем не тот случай когда деструкторы запускаются на указателях, понимаете?
Для начала, оставьте полиморфное наследование. Оставьте любое. Напишите класс в котором деструктор пишет на экран что-то вроде "I am destuctor". Создайте динамический массив. Удалите его delete[]. Подумайте о том что происходит. Почитайте.
А потом возвращаясь к наследованию (полиморфному) задумайтесь о том зачем оно нужно. Наследники имеют разные с базовым классом размеры, - больше обычно и разные между собой также. Они не могут вперемежку размещаться в одном массиве. Но профит от полиморфного поведения именно в возможности вызывать метод на коллекции гарантируя его полиморфное выполнение. Единственный выход, это массив указателей на базовый класс. Где уже сами указатели (объекты массива) указывают на разные полиморфные объекты. Это совсем не то, что Вы сделали инициализировав указатель базового класса массивом объектов наследника.
Я имел дело с классами динамический массив (двумерными тоже, перегружал операторы в них, почти всегда никуда не глядя, и механизм работы мягко говоря у меня в печенках теперь), а вы можете тогда посоветовать какую-нибудь литературу по данному вопросу, с таким наследованием я столкнулся впервые, обычно везде рассказывают про указатели и этим ограничиваются
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
22.07.2018, 23:20 8
Лучший ответ Сообщение было отмечено Mikelyndgelo как решение

Решение

Цитата Сообщение от Mikelyndgelo Посмотреть сообщение
и механизм работы мягко говоря у меня в печенках теперь
Это тоже результат. Осталось переместить это выше.
Цитата Сообщение от Mikelyndgelo Посмотреть сообщение
а вы можете тогда посоветовать какую-нибудь литературу по данному вопросу
Mikelyndgelo, то о чём речь есть везде. Вопрос в том, что Вы очень торопитесь. Для начала поймите, что вызывая виртуальный метод (не только деструктор, конечно) на экземляре Вы вызываете его не виртуально. А вызвав на указателе (или ссылке) на базовый класс Вы вызываете метод того объекта на который в данный момент смотрит этот укахатель. Именно для этого в языке который пароноидально относится к приведениям, приведения указателя наследника к указателю базового класса происходит автоматически. Поэкспериментируйте с вызовом полиморфных методов на указателях базового класса безо всяких массивов. А уже потом создавайтк массивы или векторы указателей базового класса и заселяйте их адресами разношерстной полиморфной публики и крутите в цикле запуская полиморфный метод sound() и пусть щенок лает, котёнок мяукает, корова мычит...
1
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
22.07.2018, 23:29 9
Mikelyndgelo, и ещё. Там у Вас конструкторы перемещения вроде. И это хорошо. Если хорошо. Но понимаете ли Вы что в наследнике у Вас уже 2 массива, 2 указателя и 2 поля size? Вы же вызвали базовый конструктор и он всё сделал, но потом Вы затенили имена базового класса именами наследника. Если оно Вам нужно - бог с ним, но я этого не вижу. Обращаться к ним можно через полное разрешение: First::arr например.
0
16 / 11 / 6
Регистрация: 18.07.2018
Сообщений: 51
22.07.2018, 23:30  [ТС] 10
IGPIGP Спасибо, может реально слишком увлекся и без базы устоявшейся двинулся в никуда
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
22.07.2018, 23:32 11
Цитата Сообщение от Mikelyndgelo Посмотреть сообщение
IGPIGP Спасибо, может реально слишком увлекся и без базы устоявшейся двинулся в никуда
Это обычное дело.
0
22.07.2018, 23:32
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.07.2018, 23:32
Помогаю со студенческими работами здесь

Двумерный динамический массив (Получить векторный столбец, элементы которого являются наименьшим по модулю столбцов исходной матрицы)
Подскажите, что делаю не так. Задание такое: Дана матрица A(n,m). Получить векторный столбец,...

Сделать динамический массив структур, причем в структуре так же существует динамический массив
Добрый день. Есть такая пзадача: нужно сделать динамический массив структур, причем в структуре...

Скопировать динамический массив в другой массив только с положительными элементами из первого
Пользователь вводит размер массива и сам массив. Программа копирует в другой массив только...

Дан массив A(N) (N - четное). Сформировать массив B(M), элементами которого являются средние арифметические
Помогите решить задачу,пожл! Дан массив A(N) (N - четное). Сформировать массив B(M), элементами...

Массив: Создать новый массив, элементами которого являются все отрицательные элементы массива C
1)Дан массив C(n). Создать новый массив, элементами которого являются все отрицательные массива C.

Дан массив A(N) (N – четное). Сформировать массив В(М), элементами которого являются средние арифметические соседних
Дан массив A(N) (N – четное). Сформировать массив В(М), элементами которого являются средние...


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

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