Alvin Seville
343 / 273 / 134
Регистрация: 25.07.2014
Сообщений: 4,537
Записей в блоге: 9
1

Класс динамического массива. Почему не компилируется?

12.02.2019, 03:51. Показов 1315. Ответов 18
Метки нет (Все метки)

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
// Stack.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
//
 
#include "pch.h"
#include <iostream>
 
#include <string>
#include <array>
 
using namespace std;
 
template<typename t>
using ptr_t = t*;
 
template<typename t>
class dynamic_array_t
{
private:
    ptr_t<t> source;
    int count;
    
    void throw_if_index_out_of_range(int index)
    {
        if (index < 0 || index >= count)
            throw out_of_range("index должен лежать в границах массива");
    }
 
public:
    int get_count()
    {
        return count;
    }
 
    t get_at(int index)
    {
        throw_if_index_out_of_range(index);
        return *(source + index);
    }
 
    void set_at(t value, int index)
    {
        throw_if_index_out_of_range(index);
        source[index] = value;
    }
 
    dynamic_array_t(int count = 0)
    {
        if (count < 0)
            throw out_of_range("count должен быть неотрицательным");
 
        source = (ptr<t>)malloc(count * sizeof(t));
    }
 
    template<typename __t>
    static void copy_to(dynamic_array_ptr_t<__t> source, dynamic_array_ptr_t<__t> target, int index = 0)
    {
        if (source == nullptr || target == nullptr)
            throw invalid_argument("source и target не должны быть nullptr");
 
        if (index < 0 || index >= target->get_count())
            throw out_of_range("index должен лежать в границах массива");
 
        if (source->get_count() > target->get_count())
            throw invalid_argument("source->get_count() не должно превышать target->get_count()");
 
        for (size_t i = 0; i < source->get_count(); i++)
            target->set_at(source[i], index + i);
    }
 
    template<typename __t>
    static void reverse(dynamic_array_ptr_t<__t> source)
    {
        int j = --source->get_count();
        for (size_t i = 0; i < source->get_count() / 2; i++)
            source->set_at(source[j - i], i);
    }
 
    template<typename __t>
    static void resize(dynamic_array_ptr_t<__t> &source, int count)
    {
        if (source == nullptr)
            throw invalid_argument("source не должен быть nullptr");
 
        if (count < 0)
            throw out_of_range("count должен быть неотрицательным");
 
        dynamic_array_ptr_t<__t> result = new dynamic_array_t<__t>(count);
        dynamic_array_t::copy_to(source, result, 0);
        source = result;
    }
 
    template<typename __t>
    static void fill(dynamic_array_ptr_t<__t> source, __t value = default(__t))
    {
        for (size_t i = 0; i < source->get_count(); i++)
            source.set_at(value, i);
    }
};
 
template<typename t>
using dynamic_array_ptr_t = ptr_t<dynamic_array_t<t>>;
 
int main()
{
    dynamic_array_ptr_t<int> sptr = new dynamic_array_t<int>(1);
}
Почему не компилируется? Я не знаю как исправить ошибки в коде. Вернее, я не вижу, почему ошибка.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.02.2019, 03:51
Ответы с готовыми решениями:

Создайте класс динамического массива, в котором реализована проверка выхода за границы массива
Создайте класс динамического массива, в котором реализована проверка выхода за границы массива....

Создайте класс динамического массива, в котором реализована проверка выхода за границы массива
Народ подскажите такую вещь я написал программку для вставки элементов в массив при этом...

Создайте класс динамического массива, в котором реализована проверка выхода за границы массива
Создайте класс динамического массива, в котором реализована проверка выхода за границы массива....

Класс динамического массива с проверкой выхода за границы массива
Задание такое: Создайте класс динамического массива, в котором реализована проверка выхода за...

18
2063 / 1543 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
12.02.2019, 05:41 2
тип dynamic_array_ptr_t - полное отсутствие всякого присутсвия. Все остальные ошибки следствие этой. по всей видимости там везде где dynamic_array_ptr_t должен быть dynamic_array_t.
1
Alvin Seville
343 / 273 / 134
Регистрация: 25.07.2014
Сообщений: 4,537
Записей в блоге: 9
12.02.2019, 10:10  [ТС] 3
Fulcrum_013, погоди, так мне же нужен указатель на массив, что есть dynamic_array_ptr_t.
0
18985 / 9927 / 2426
Регистрация: 30.01.2014
Сообщений: 17,449
12.02.2019, 17:31 4
Соколиный глаз,
1) Шаблон dynamic_array_ptr_t не объявлен в месте использования. Видимо нужно перенести его выше. И предварительно объявление dynamic_array_t тоже.

2) Непонятный default в шаблонной функции fill (это намек на то, что этого тут быть не может).

3) Начинать идентификаторы с двух нижних подчеркиваний - искать приключений на пятую точку. Не делайте так.

4) Модифицировать временный объект встроенного типа (ш. функция reverse) не допускается.

5) malloc не создает объекты. Ваш массив будет работать только для тривиальных типов.

6) деструктор (и констр. копирования, оператор присваивания) потеряли.

Добавлено через 3 минуты
Соколиный глаз, вообще данный код классический пример оверинжиниринга (уж не обижайтесь, кто еще вам правду скажет?). Т.е. сделаны простые вещи необоснованно сложными путями. А потом у людей складывается впечатление, будто все программирование на С++ такое.
1
Alvin Seville
343 / 273 / 134
Регистрация: 25.07.2014
Сообщений: 4,537
Записей в блоге: 9
12.02.2019, 19:05  [ТС] 5
DrOffset,
2) Ну, значение по умолчанию для __t хотел взять.
3) Хорошо, понял.
4) А как тогда?
5) А если надо для произвольных?
6) Да, спасибо, допишу.
Это не C++ виноват, а я, ибо нет опыта программирования на нем. Пусть те, кто читают эту тему эту строчку прочитают.

Добавлено через 42 минуты
И собственно почему я делал класс динамического массива - мне требуется динамические массивы как в C#.
0
2063 / 1543 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
12.02.2019, 20:36 6
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
И собственно почему я делал класс динамического массива - мне требуется динамические массивы как в C#.
Зачем как в С#? В C++ даже те которые искоропки гораздо лучше.
0
18985 / 9927 / 2426
Регистрация: 30.01.2014
Сообщений: 17,449
12.02.2019, 20:41 7
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
Ну, значение по умолчанию для __t хотел взять.
Это выглядело бы так:
C++
1
2
template<typename __t>
static void fill(dynamic_array_ptr_t<__t> source, __t value = __t())
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
А как тогда?
C++
1
2
//        int j = --source->get_count();
int j = source->get_count() - 1;
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
А если надо для произвольных?
В вашей реализации нужно будет использовать placement new.

Цитата Сообщение от Соколиный глаз Посмотреть сообщение
мне требуется динамические массивы как в C#.
Если вам нужен контейнер по интерфейсу схожий с подобным в C#, не проще ли сделать адаптер к одному из стандартных контейнеров С++, чем писать собственный с нуля? Сделать, чтобы самописный контейнер был корректным с учетом всех требований, нетривиальная задача для новичка.
1
Alvin Seville
343 / 273 / 134
Регистрация: 25.07.2014
Сообщений: 4,537
Записей в блоге: 9
12.02.2019, 23:50  [ТС] 8
Fulcrum_013, я отказался от array<T, Size> и от vector<T>, так как мне не нравится, что там открыта внутренняя реализация. Наверное, странная причина, но я к такому не привык. В C# такого не встречал нигде. А вторая причина - array<T, Size> нельзя ресайзить. А у вектора ресайз автоматический. Хотя, конечно, можно и самому им управлять, но все же.

Добавлено через 4 минуты
DrOffset, а вообще, скажите, аллокатор требуется делать для каждого контейнера?
0
18985 / 9927 / 2426
Регистрация: 30.01.2014
Сообщений: 17,449
13.02.2019, 00:30 9
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
аллокатор требуется делать для каждого контейнера?
Аллокатор - это политика выделения\освобождения памяти. Если у вас она фиксирована будет (т.е. дизайн вашего класса не будет предполагать смены стратегии выделения памяти), то отдельно его можно вообще не делать.

Цитата Сообщение от Соколиный глаз Посмотреть сообщение
там открыта внутренняя реализация
В смысле?

Цитата Сообщение от Соколиный глаз Посмотреть сообщение
array<T, Size> нельзя ресайзить.
Ну потому что он не для этого. Отсутствие возможности забивать гвозди не может являться недостатком отвертки
0
2063 / 1543 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
13.02.2019, 00:33 10
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
а вообще, скажите, аллокатор требуется делать для каждого контейнера?
Он делается для другого способа аллокации. Т.е. к примеру не в ОЗУ вообще. Или в ОЗУ но по другому (к примеру в каком то большом буфере куски выделяются). Или для связного списка из пула константного выделения к примеру. И т.п. Т.е. по ходу для указания альтернативного способа получения/высвобождения памяти.

Добавлено через 2 минуты
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
В C# такого не встречал нигде.
С#в плане искоробочной библиотеки это сильно урезанная дельфа. Если дело касается дельфы то первое что там делаю это оборачиваю ее штатный массив в дженерик для автоматического ресайза. Только выходит оно черезчур криво потому как дженерики не есть шаблоны..
1
18985 / 9927 / 2426
Регистрация: 30.01.2014
Сообщений: 17,449
13.02.2019, 00:33 11
Соколиный глаз, Попытка перетащить привычки из языка с другой парадигмой без тщательного осмысления может привести к печальным последствиям Это все равно, что при переходе, например, с паскаля пытаться дефайнить фигурные скобки на begin\end, потому что не привык. В общем, при изучении нового языка - задача понять его идеологию, а не насаждать там чужую. Иначе, самообман какой-то получается.
1
2063 / 1543 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
13.02.2019, 05:27 12
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
Наверное, странная причина, но я к такому не привык. В C# такого не встречал нигде.
Писать на С++ в том же духе как на дельфе С# и жабе исключительно непродуктивно (по меркам С++) и вообще вредно для здоровья.

Добавлено через 1 час 16 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
В общем, при изучении нового языка - задача понять его идеологию, а не насаждать там чужую. Иначе, самообман какой-то получается.
Это да есть такое. к примеру вот тут
C++
1
dynamic_array_ptr_t<int> sptr = new dynamic_array_t<int>(1);
использование new для распределения самого массива а не только буфера у него под капотом лучший способ и геморой поиметь и в общем то все прелести плюсов похерить.

Добавлено через 3 часа 34 минуты
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
А у вектора ресайз автоматический. Хотя, конечно, можно и самому им управлять, но все же.
А вам нужно что то типа Array.SetSize(n)? Так в сторону увеличения оно возможно только для типа элементов у которого есть конструктор по умолчанию, что далеко не есть тру для всех возможных типов. А в сторону уменьшения такая штука у вектора есть.
1
Alvin Seville
343 / 273 / 134
Регистрация: 25.07.2014
Сообщений: 4,537
Записей в блоге: 9
13.02.2019, 07:01  [ТС] 13
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
А вам нужно что то типа Array.SetSize(n)?
Типа Array.Resize. Но, Вы меня правильно всё равно поняли.

Добавлено через 8 минут
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
// Stack.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
//
 
#include "pch.h"
#include <iostream>
 
#include <string>
#include <array>
 
using namespace std;
 
template<typename t>
using ptr_t = t*;
 
template<typename t>
class dynamic_array_t;
 
template<typename t>
using dynamic_array_ptr_t = ptr_t<dynamic_array_t<t>>;
 
template<typename t>
class dynamic_array_t
{
private:
    ptr_t<t> source;
    int count;
    
    void throw_if_index_out_of_range(int index)
    {
        if (index < 0 || index >= count)
            throw out_of_range("index должен лежать в границах массива");
    }
 
public:
    int get_count()
    {
        return count;
    }
 
    t get_at(int index)
    {
        throw_if_index_out_of_range(index);
        return *(source + index);
    }
 
    void set_at(t value, int index)
    {
        throw_if_index_out_of_range(index);
        source[index] = value;
    }
 
    dynamic_array_t(int count = 0)
    {
        if (count < 0)
            throw out_of_range("count должен быть неотрицательным");
 
        source = (ptr<t>)malloc(count * sizeof(t));
    }
 
    template<typename __t>
    static void copy_to(dynamic_array_ptr_t<__t> source, dynamic_array_ptr_t<__t> target, int index = 0)
    {
        if (source == nullptr || target == nullptr)
            throw invalid_argument("source и target не должны быть nullptr");
 
        if (index < 0 || index >= target->get_count())
            throw out_of_range("index должен лежать в границах массива");
 
        if (source->get_count() > target->get_count())
            throw invalid_argument("source->get_count() не должно превышать target->get_count()");
 
        for (size_t i = 0; i < source->get_count(); i++)
            target->set_at(source[i], index + i);
    }
 
    template<typename __t>
    static void reverse(dynamic_array_ptr_t<__t> source)
    {
        int j = source->get_count() - 1;
        for (size_t i = 0; i < source->get_count() / 2; i++)
            source->set_at(source[j - i], i);
    }
 
    template<typename __t>
    static void resize(dynamic_array_ptr_t<__t> &source, int count)
    {
        if (source == nullptr)
            throw invalid_argument("source не должен быть nullptr");
 
        if (count < 0)
            throw out_of_range("count должен быть неотрицательным");
 
        dynamic_array_ptr_t<__t> result = new dynamic_array_t<__t>(count);
        dynamic_array_t::copy_to(source, result, 0);
        source = result;
    }
 
    template<typename __t>
    static void fill(dynamic_array_ptr_t<__t> source, __t value = __t())
    {
        for (size_t i = 0; i < source->get_count(); i++)
            source->set_at(value, i);
    }
};
 
int main()
{
    dynamic_array_ptr_t<int> sptr = new dynamic_array_t<int>(1);
}
Что значит:
синтаксическая ошибка: ожидался токен "выражение", а не ")" - строка 57
?
0
2063 / 1543 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
13.02.2019, 07:30 14
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
Что значит:
наверное вот так хочет
C++
1
source=(ptr_t<t>)malloc(count * sizeof(t));
Добавлено через 5 минут
Цитата Сообщение от Соколиный глаз Посмотреть сообщение
Типа Array.Resize. Но, Вы меня правильно всё равно поняли.
Вообще это можно слепить для тех у кого есть конструктор по умолчанию путем специализаций шаблона. Т.е. дополняется метод установки размера для тех у кого есть конструктор по умолчанию а у тех у кого нет только метод обрезки. К вектору штатному это прикрутить не пробовал а со своим это как два пальца об асфальт.
1
18985 / 9927 / 2426
Регистрация: 30.01.2014
Сообщений: 17,449
13.02.2019, 14:21 15
Соколиный глаз, Все хотел спросить. Зачем static функции? Они же ведут себя как функции-члены у вас. Так в чем замысел этого очевидного усложнения?
Также хотелось бы получить ответ по поводу открытости внутренней реализации у стандартных контейнеров.
0
Alvin Seville
343 / 273 / 134
Регистрация: 25.07.2014
Сообщений: 4,537
Записей в блоге: 9
13.02.2019, 22:15  [ТС] 16
Цитата Сообщение от DrOffset Посмотреть сообщение
Также хотелось бы получить ответ по поводу открытости внутренней реализации у стандартных контейнеров.
Обратимся к array<T, size>. Доступ к членам, начинающихся с нижнего подчёркивания не ограничен. То же самое и в других контейнерах.
0
2063 / 1543 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
13.02.2019, 23:29 17
Соколиный глаз, В векторе все в привате.
в либе которая к вижуал студии 17-ой идет в строках 604-605
C++
1
2
private:
    _Compressed_pair<_Alty, _Vector_val<_Val_types>> _Mypair;
Добавлено через 5 минут
а в public они у вспомогательного класса _Vector_val экземпляр которого вектор держит в private
0
18985 / 9927 / 2426
Регистрация: 30.01.2014
Сообщений: 17,449
13.02.2019, 23:41 18
Соколиный глаз, По поводу array - у этого есть техническое обоснование, а у остальных контейнеров ничего подобного нет. Все методы, начинающиеся с подчеркивания, закрыты для использования. Если вы судите о "доступности" по выпадающему списку автодополнения в IDE, то это проблема движка автодополнения, который добавляет туда лишнее, а не контейнера.
В любом случае вы можете сделать адаптер на базе стандартного контейнера и спрятать все, что вам нужно спрятать.

И все-таки в чем смысл static в вашем коде?

Ничего страшного нет в том, чтобы в целях обучения написать свой контейнер, но нужно понимать, что далеко не сразу получится его сделать хотя бы таким же безопасным, как стандартный.
1
Alvin Seville
343 / 273 / 134
Регистрация: 25.07.2014
Сообщений: 4,537
Записей в блоге: 9
14.02.2019, 03:19  [ТС] 19
DrOffset, я хотел сделать статические методы... Как в C# у класса Array.
0
14.02.2019, 03:19
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.02.2019, 03:19
Помогаю со студенческими работами здесь

Почему при создании динамического массива через new ячейки массива имеют значение -842150451?
Я хотел бы узнать почему при создании динамического массива через операцию new ячейки массива имеют...

Класс динамического массива
Создайте класс Array. Класс Array - это класс динамического массива. Рассмотреть одномерный...

Создать класс динамического массива
Задание заключается в следущем: Создать динамический класс для выполнения операций над...

Класс для двумерного динамического массива
Вот написал код для двумерного динамического массива с перегруженым оператором= и +. Собственно...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

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