Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
vadim_bz
1 / 1 / 1
Регистрация: 11.04.2015
Сообщений: 35
#1

Приём константных векторов класса, как аргументов в методе другого класса - C++

20.04.2016, 21:22. Просмотров 302. Ответов 12
Метки нет (Все метки)

Есть такой класс:
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
class Order {
    private:
        int numberOrder;
        map <string, int> catalogDish;
        double totalCost;
    public:
        Order () {}
        Order (int numberOrder, const vector <string> &vline, double totalCost) {
            this->numberOrder = numberOrder;
            this->totalCost = totalCost;
            for (int i = 0; i != vline.size (); ++i)
                RegexForCatalogDish (vline[i], catalogDish);
            }
    public:
        int getOrderNumberOrder () { return numberOrder; }
        double getOrderTotalCost () { return totalCost; }
        int sizeOrderCatalogDish () {
            int i = 0;
            for (map <string, int>::iterator it = catalogDish.begin (); it != catalogDish.end (); ++it, ++i);
            return i;
            }
        pair <string, int> getOrderCatalogDish (int unit) {
            int i = 0;
            for (map <string, int>::iterator it = catalogDish.begin (); it != catalogDish.end (); ++it, ++i)
                if (i == unit)
                    return pair <string, double> (it->first, it->second);
            }
    };
В дальнейшем использую для хранения данных вектор этого класса:
C++
1
vector <Order> orders;
И существует отдельно класс с методами для работы с вектором класса Order:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class VOrder { //методы для vector <Order>
    public:
        //количество блюд //CONST!!!
        int countOrderDishes (const vector <Order> &orders) { 
                int x = 0;
                for (int i = 0; i != orders.size (); ++i)
                    for (int j = 0; j != orders[i].sizeOrderCatalogDish (); ++j, ++x);
                return x;
             }
        //возвращает элементы чека линейно, без учёта номера заказа, по номеру элемента //CONST!!!
        pair <string, int> getOrderUnit (const vector <Order> &orders, int unit) {
                for (int i = 0, x = 0; i != orders.size (); ++i)
                    for (int j = 0; j != orders[i].sizeOrderCatalogDish (); ++j, ++x)
                        if (x == unit && unit >= 0)
                            return orders[i].getOrderCatalogDish(j);
            }
    };
Так вот собственно если в классе VOrder делать аргументы у методов константными (4 и 11 строка), дабы показать что сам vector <Order> orders не изменится, компилятор будет ругаться, и правильно сделает, ибо в вызванных методах уже класса Order запустится цикл, создадутся переменные цикла, значение которых будут изменяться. Хотя при этом данные самого vector <Order> orders никаким изменениям не подвергнутся.
Так вот вопрос, может есть способ всё таки каким-нибудь образом обозначить, что данные в vector <Order> orders не изменятся?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.04.2016, 21:22
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Приём константных векторов класса, как аргументов в методе другого класса (C++):

Ошибка при вызове метода класса в методе другого класса
Господа программисты, возникла такая проблема. При вызове метода класса в...

Создать класс CheckerBoard (особенности строения класса - инициализация константных членов класса)
Вот код: #include &lt;iostream&gt; #include &lt;string&gt; using namespace std;...

Как в методе класса вызвать другой метод того же класса?
class mate { public: int AplusB(int A, int B) { return A+B; } int...

Как получить private переменную класса, функцей членом другого класса
Игра змейка: Есть класс поле в котором содержится размеры поля: class...

Как переместить из стека одного класса в массив другого класса?
// HW_on.24.11_classStack_SantaClaus.cpp: определяет точку входа для...

Массив объектов одного класса как поле другого класса
Доброе время суток. Мне тут в универе задали лабу, нужно создать класс полем...

12
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
20.04.2016, 22:11 #2
vadim_bz, нарушаешь const-корректность, вот и ругается. У тебя функции не меняют состояние класса, следовательно они должны быть константными.
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
class Order {
    private:
        int numberOrder;
        map <string, int> catalogDish;
        double totalCost;
    public:
        Order () {}
        Order (int numberOrder, const vector <string> &vline, double totalCost) {
            this->numberOrder = numberOrder;
            this->totalCost = totalCost;
            for (int i = 0; i != vline.size (); ++i)
                RegexForCatalogDish (vline[i], catalogDish);
            }
    public:
        int getOrderNumberOrder () const { return numberOrder; }
        double getOrderTotalCost () const { return totalCost; }
        int sizeOrderCatalogDish () const {
            int i = 0;
            for (map <string, int>::const_iterator it = catalogDish.begin (); it != catalogDish.end (); ++it, ++i);
            return i;
            }
        pair <string, int> getOrderCatalogDish (int unit) const {
            int i = 0;
            for (map <string, int>::const_iterator it = catalogDish.begin (); it != catalogDish.end (); ++it, ++i)
                if (i == unit)
                    return std::make_pair(it->first, it->second);
            }
    };
Цитата Сообщение от vadim_bz Посмотреть сообщение
Так вот вопрос, может есть способ всё таки каким-нибудь образом обозначить что данные в vector <Order> orders
Вот и обозначай, как сейчас написано. Только с const-корректностью разберись.

Добавлено через 12 минут
PS (не по теме).
* Везде, где индексы, int поменять на size_t.
* Дописать возвращаемые значения в функции getOrderCatalogDish и getOrderUnit.
* Не использовать тяжеловесные функции вроде sizeOrderCatalogDish в условии цикла.
* Функция sizeOrderCatalogDish () может быть реализована через std::map<>::size()
* В конструкторе следует использовать список инициализации, а не присваивание.
* Функция getOrderCatalogDish крайне неудачная, по сути она линейно ищет в map, это очень неэффективно, возможно стоит подумать о дополнительном индексном контейнере с произвольным доступом.
1
vadim_bz
1 / 1 / 1
Регистрация: 11.04.2015
Сообщений: 35
20.04.2016, 23:52  [ТС] #3
DrOffset, выразился я конечно крайне коряво, но вы поняли, спасибо.
Можно тогда под шумок ещё пару вопросов?)
1) sizeOrderCatalogDish я поправил и реализовал через std::map<>::size(), в таком случае допускается ли использование её в условии цикла? Перестаёт ли быть тяжеловесной?
2) Да конечно понимаю, что метод getOrderCatalogDish перебирает кучу элементов контейнера прежде чем выведет нужный, и что следовало в таком случае под нужды использовать какой-нибудь другой контейнер, не подскажете тогда какой контейнер лучше использовать? Эта связка <string, int> всё-таки будет часто перебираться поэлементно.
3) И о самом классе VOrder, то что он хранит только методы для работы с vector <Order>, а самого vector <Order> (в private поле) в себе не содержит, никак не противоречит принципам ООП? А то препод говорит что это процедурный код, но добавление туда самого vector <Order> либо избавление от VOrder, просто не целесообразны и приводят только к усложнению кода.
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
21.04.2016, 00:10 #4
Цитата Сообщение от vadim_bz Посмотреть сообщение
Перестаёт ли быть тяжеловесной?
Скажем так: и да и нет. Вообще сейчас стандарт гарантирует O(1) для size() всех контейнеров. Но это гарантия стандарта, а не реализации.
Почему такое желание запихнуть ее именно в условие? Она же не меняется от итарации к итерации. В этом нет никакого смысла.
Можно просто взять за правило, что если размер в пределах цикла меняться не может, то выносить его получение отдельно. Например:
C++
1
2
3
4
for(size_t i = 0, len = container.size(); i < len; ++i)
{
     //.....
}
Но вообще это конечно мелочный довольно вопрос. Просто, по крайней мере, ты должен понимать когда так можно сделать, а когда нельзя.
Цитата Сообщение от vadim_bz Посмотреть сообщение
какой-нибудь другой контейнер, не подскажете тогда какой контейнер лучше использовать?
Если ограничиваться std::, то можно просто хранить элементы в std::vector< int >. А в std::map держать индекс нужного элемента std::map<std::string, size_t>. Добавлять и удалять в них "вместе". При этом, когда нам нужен поиск по ключу, мы обращаемся к map, получаем индекс и быстро запрашиваем у вектора значение элемента. Если нужен доступ в порядке добавления, по номеру, то обращаемся сразу к вектору. Операция индексации у него мгновенная.
Цитата Сообщение от vadim_bz Посмотреть сообщение
то что он хранит только методы для работы с vector <Order>, а самого vector <Order> (в private поле) в себе не содержит, никак не противоречит принципам ООП?
Громких выводов делать не буду, но это по крайней мере слегка шатает здравый смысл.
Впрочем, эти функции в этом случае можно сделать статическими. А еще лучше заменить класс на namespace и поместить эти функции туда.

Цитата Сообщение от vadim_bz Посмотреть сообщение
добавление туда самого vector <Order> либо избавление от VOrder просто не целесообразно
Почему?
1
vadim_bz
1 / 1 / 1
Регистрация: 11.04.2015
Сообщений: 35
21.04.2016, 00:53  [ТС] #5
В программе я работаю именно с vector <Order>, а сам класс VOrder был создан для обращения к элементам map <string, int> catalogDish, в тех случаях, когда не нужны данные двух других полей (numberOrder, totalCost) и можно было бы иметь за один проход цикла весь список данных из map <string, int> catalogDish от разных элементов vector <Order>, вот пример:
C++
1
2
3
for (int i = 0; i != vorder.countOrderDishes (orders); ++i)
    if (!vcategorymenu.getMenuPrice(menu,vorder.getOrderUnit(orders,i).first))
        cout << endl << "ERROR: In orders-" << date << " unknown dish: " + vorder.getOrderUnit(orders,i).first << endl;
Если просто избавиться VOrder то там где можно было обойтись одним циклом надо было бы городить один в другом (в худшем случае выходило до 5 вложений против 3х). Вот например тот же код, но без VOrder:
C++
1
2
3
4
for (int i = 0; i != orders.size() ; ++i)
    for (int j = 0; j != orders[i].sizeOrderCatalogDish(); ++j)
        if (!vcategorymenu.getMenuPrice(menu,orders[i].getOrderCatalogDish(j).first)
            cout << endl << "ERROR: In orders-" << date << " unknown dish: " + orders[i].getOrderCatalogDish(j).first << endl;
Если же добавить
Цитата Сообщение от vadim_bz Посмотреть сообщение
vector <Order> (в private поле)
то это придётся добавлять кучу всего что уже сам класс Order имеет для доступа к private ещё и всю программу переписывать под новый тип.
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
21.04.2016, 08:28 #6
vadim_bz, замени класс на namespace и будет нормально.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        
namespace VOrder
{
        //количество блюд
        inline size_t countOrderDishes (const vector <Order> &orders) { 
                size_t x = 0;
                for (size_t i = 0; i != orders.size (); ++i)
                    for (size_t j = 0; j != orders[i].sizeOrderCatalogDish (); ++j, ++x);
                return x;
        }
        //возвращает элементы чека линейно, без учёта номера заказа, по номеру элемента
        inline pair <string, int> getOrderUnit (const vector <Order> &orders, size_t unit) {
                for (size_t i = 0, x = 0; i != orders.size (); ++i)
                    for (size_t j = 0; j != orders[i].sizeOrderCatalogDish (); ++j, ++x)
                        if (x == unit)
                            return orders[i].getOrderCatalogDish(j);
                return pair <string, int>();
        }
} // VOrder
Заодно избавишься от необходимости создавать объект, который не выражает никакого состояния.

Цитата Сообщение от vadim_bz Посмотреть сообщение
всю программу переписывать
А вот к этому вообще нужно быть готовым.
Наивно полагать, что то, что получится в первый раз, сразу будет хорошо.
0
vadim_bz
1 / 1 / 1
Регистрация: 11.04.2015
Сообщений: 35
21.04.2016, 12:22  [ТС] #7
DrOffset, решил попробовать сделать по правильному) Взглянете? Так будет лучше?

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
class CatalogDishOrder {
    private:
        string name;
        int count;
    public:
        CatalogDishOrder () {}
        CatalogDishOrder (string name, int count) {
            this->name = name;
            this->count = count;
            }
    public:
        string getCatalogDishName () { return name; }
        int getCatalogDishCount () { return count; }
    };
 
class Order {
    private:
        int numberOrder;
        vector <CatalogDishOrder> catalogDish;
        double totalCost;
    public:
        Order () {}
        Order (int numberOrder, const vector <string> &vline, double totalCost) {
            this->numberOrder = numberOrder;
            this->totalCost = totalCost;
            for (size_t i = 0; i != vline.size (); ++i)
                RegexForCatalogDish (vline[i], catalogDish);
            }
    public:
        int getOrderNumberOrder () { return numberOrder; }
        double getOrderTotalCost () { return totalCost; }
        int sizeOrderCatalogDish () const { return catalogDish.size(); }
        CatalogDishOrder getOrderCatalogDish (int unit) {
            if (unit < sizeOrderCatalogDish() && unit >= 0)
                return catalogDish[unit];
            }
    };
 
class Orders { //методы для vector <Order>
    private:
        vector <Order> orders;
    public:
        int sizeOrders () {
            return orders.size ();
            }
    public:
        void addNewOrder (int numberOrder, const vector <string> &vline, double totalCost) {
            oreders.push_back (Order (numberOrder, vline, totalCost));
            }
        int getOrderNumberOrder (int numberOrder) {
            if (numberOrder < orders.size() && numberOrder >= 0)
                return orders[numberOrder].getOrderNumberOrder();
            else 
                return 0;
            }
        double getOrderTotalCost (int numberOrder) {
            if (numberOrder < orders.size() && numberOrder >= 0)
                return orders[numberOrder].getOrderTotalCost();
            else 
                return 0;
            }
        int sizeOrderCatalogDish (int numberOrder) {
            if (numberOrder < orders.size() && numberOrder >= 0)
                return orders[numberOrder].sizeOrderCatalogDish();
            else 
                return 0;
            }
        CatalogDishOrder getOrderCatalogDish (int numberOrder, int unit) {
            if (numberOrder < orders.size() && numberOrder >= 0)
                return orders[numberOrder].getOrderCatalogDish (unit);
            }
    public:
        //количество блюд
        int countOrderDishes () { 
                int x = 0;
                for (size_t i = 0; i != orders.size (); ++i)
                    for (size_t j = 0; j != orders[i].sizeOrderCatalogDish (); ++j, ++x);
                return x;
             }
        //возвращает элементы чека линейно, без учёта номера заказа, по номеру элемента
        pair <string, int> getOrderUnit (const vector <Order> &orders, int unit) {
                for (size_t i = 0, x = 0; i != orders.size (); ++i)
                    for (size_t j = 0; j != orders[i].sizeOrderCatalogDish (); ++j, ++x)
                        if (x == unit && unit >= 0)
                            return orders[i].getOrderCatalogDish(j);
            }
    };
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
21.04.2016, 18:42 #8
Цитата Сообщение от vadim_bz Посмотреть сообщение
Так будет лучше?
Да, лучше.
Расставь только const`ы функциям, которые не меняют состояние класса.
0
vadim_bz
1 / 1 / 1
Регистрация: 11.04.2015
Сообщений: 35
21.04.2016, 21:35  [ТС] #9
Всё оказалось куда проще)

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
class Order {
    private:
        vector <pair <string, int>> catalogDish;
        double totalCost;
    public:
        Order () {}
        Order (const vector <string> &vline, double totalCost) {
            this->totalCost = totalCost;
            for (size_t i = 0; i != vline.size (); ++i)
                RegexForCatalogDish (vline[i], catalogDish);
            }
    public:
        double getOrderTotalCost () const { return totalCost; }
        int sizeOrderCatalogDish () const { return catalogDish.size(); }
        pair <string, int> getOrderCatalogDish (int unit) const {
            if (unit < catalogDish.size() && unit >= 0)
                return catalogDish[unit];
            }
    };
 
class Orders {
    private:
        vector <Order> orders;
    public:
        int sizeOrders () const { return orders.size (); }
        void addNewOrder (int numberOrder, const vector <string> &vline, double totalCost) {
            orders.push_back (Order (vline, totalCost));
            }
        const Order &operator[] (int numberOrder) const {
            if (numberOrder < orders.size() && numberOrder >= 0)
                return orders[numberOrder];
            }
        //количество блюд
        int countOrderDishes () { 
                int x = 0;
                for (size_t i = 0; i != orders.size (); ++i)
                    for (size_t j = 0; j != orders[i].sizeOrderCatalogDish (); ++j, ++x);
                return x;
             }
        //возвращает элементы чека линейно, без учёта номера заказа, по номеру элемента
        pair <string, int> getOrderUnit (const vector <Order> &orders, int unit) {
                for (size_t i = 0, x = 0; i != orders.size (); ++i)
                    for (size_t j = 0; j != orders[i].sizeOrderCatalogDish (); ++j, ++x)
                        if (x == unit && unit >= 0)
                            return orders[i].getOrderCatalogDish(j);
            }
    };
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
21.04.2016, 21:48 #10
vadim_bz, это все хорошо, только куда опять return`ы потерял?
Что будет, если мы передадим, например, в getOrderUnit unit, который не найдется в orders?
0
vadim_bz
1 / 1 / 1
Регистрация: 11.04.2015
Сообщений: 35
21.04.2016, 21:52  [ТС] #11
DrOffset, просто не придумал что в таком случае лучше вернуть)) Что-нибудь вроде return make_pair("",0); ?
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
21.04.2016, 21:55 #12
Цитата Сообщение от vadim_bz Посмотреть сообщение
просто не придумал что в таком случае лучше вернуть))
Выше был вариант.

В зависимости от логики, планируемой в вызывающем коде, можно, например, еще бросить исключение.
0
vadim_bz
1 / 1 / 1
Регистрация: 11.04.2015
Сообщений: 35
21.04.2016, 22:29  [ТС] #13
Цитата Сообщение от DrOffset Посмотреть сообщение
Выше был вариант
Оу, пардон, не заметил)

Цитата Сообщение от DrOffset Посмотреть сообщение
В зависимости от логики, планируемой в вызывающем коде
Ну поэтому в общем и не стал с этим заморачиваться (зря конечно), так как функция getOrderUnit всегда будет вызываться в цикле в условии которого будет проверяться не достиг ли итератор countOrderDishes.

В общем спасибо большое за помощь)
0
21.04.2016, 22:29
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.04.2016, 22:29
Привет! Вот еще темы с решениями:

Как сделать, чтобы функция класса могла работать с обьектами другого класса
есть класс к примеру class One и класс к примеру class Two нужно чтобы...

Наследование: Как мне определить любой из методов заданного класса внутри другого класса?
Добрый день, подскажите пожалуйста, что я делаю не так Есть файл Container.h...

Массив объектов класса как член другого класса
Здравствуйте. У меня тут возникла проблемка #include &quot;main.h&quot; class...

Инициализация экземпляра класса, как поле другого класса
Всем доброго времени суток ! Есть класс: class a{ public: a(int...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru