882 / 467 / 92
Регистрация: 10.06.2014
Сообщений: 2,676
1

Константный массив в статичном поле класса

06.10.2016, 11:58. Показов 4615. Ответов 24
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Мне нужно создать константный массив в статичном поле класса. Потому что данные которые мне нужны только для чтения и постоянно одинаковые и не будут изменяться а возвращаться должны по ссылке что бы не создавать копию которая не нужна.
Для этого решил использовать std::map (если можно более эффективным способом, буду рад предложениям)
Сделал рабочий вариант, но вынужден использовать .at вместо оператора [] так как он не может быть константным в связи с тем что с помощью него можно не только читать но и писать.
Читал что более грамотно через map::value_type (подскажите пожалуйста, как правильнее)
Так же очень важно для меня сделать этот массив статичным что бы не выделять память заново под его данные при создании нового экземпляра, но при указании данного поля статичным программа не компилируется

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
#include <map>
 
int main()
{
class X
{
    const std::map<int,std::string> m = { {3, "three"}, {6, "six"}};
 
    public:
    const std::string& getValue(const int i) const
    {
        return m.at(i);
    }
};
  
  X x;
  std::cout << x.getValue(3);
  return 0;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.10.2016, 11:58
Ответы с готовыми решениями:

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

Статический константный член-класса
Добрый день, что компилятору не нравится? VS 2013 // рекурсивное шаблоное метапрограммирование ...

Статический константный объект класса
Извиняюсь за создание второй темы, но ...typedef std::vector&lt;int&gt; VI; class matrix { ...

Константный объект класса квадратная матрица
Здравствуйте! Подскажите, пожалуйста, возможно ли и если да, то как создать константный объект...

24
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.10.2016, 12:05 2
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
#include <iostream>
#include <string>
#include <map>
 
class X
{
    public:
        const std::string& getValue(int i) const
        {
            return m.at(i); // по любому нужен at() ибо друг выход за границы знач.?
        }
    
    private:
        static const std::map<int,std::string> m;
};
  
/* желательно это спрятать в сpp класса: */ 
const std::map<int,std::string> X::m = { {3, "three"}, {6, "six"}}; 
 
int main()
{
  X x;
  std::cout << x.getValue(3);
  return 0;
}
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
06.10.2016, 12:06 3
Цитата Сообщение от sys_beginner Посмотреть сообщение
но вынужден использовать .at вместо оператора [] так как он не может быть константным
так в этом и фича map, а не баг) Если вы спросите 10 - у вас вылетит ошибка и вы отследите, где что пошло не так.

Но тут лучше enum
C++
1
2
std::map<UnitType, Speed> _map;
obj.getSpeed( UnitType::Archer );
Если вы не указали значение для archer'a - то лучше пусть программа рухнит, чем вернёт вам "как бы валидное значение"
1
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.10.2016, 12:10 4
Можно
C++
1
2
3
4
 const std::string& getValue(int i) const
{
     return m.find(i)->second;
}
Но это опасно.
0
882 / 467 / 92
Регистрация: 10.06.2014
Сообщений: 2,676
06.10.2016, 12:12  [ТС] 5
Avazart,
А можно указывать присвоение значения полю внутри класса не вне него?

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Но тут лучше enum
А разве enum может играть роль ассоциативного массива? У меня ключи должны идти не последовательно, например 500, 700.
0
шКодер самоучка
2227 / 1921 / 927
Регистрация: 09.10.2013
Сообщений: 4,264
Записей в блоге: 7
06.10.2016, 12:14 6
sys_beginner, вынесите ваш массив из класса в отдельный cpp-файл и сделайте метод, реализация которого будет в том же файле.
Тем самым только этот метод будет иметь доступ к массиву.
C++
1
2
3
4
5
6
7
8
9
10
11
12
// data.h begin
#ifndef DATA_H
#define DATA_H
 
#include <string>
 
namespace data {
    const std::string& get(int);
}
 
#endif
// data.h end
C++
1
2
3
4
5
6
7
8
9
10
11
// data.cpp begin
#include <string>
#include <map>
 
namespace data {
    static const std::map<int,std::string> m = { {3, "three"}, {6, "six"}};
    const std::string& get(int id) {
        return m.at(id)
    }
}
// data.cpp end
C++
1
2
3
4
5
6
7
8
9
// main.cpp begin
#include <iostream>
#include "data.h"
 
int main() {
    std::cout << data::get(3) << endl;
    return 0;
}
// main.cpp end

Не по теме:

ух. пока я тут калякал сколько уже понаписали))

1
882 / 467 / 92
Регистрация: 10.06.2014
Сообщений: 2,676
06.10.2016, 12:15  [ТС] 7
Цитата Сообщение от Max Dark Посмотреть сообщение
вынесите ваш массив из класса в отдельный cpp-файл и сделайте метод, реализация которого будет в том же файле.
Спасибо за пример но в том то и дело что по смыслу эти данные имеют отношение к классу, хотелось бы объявить и определить его именно внутри того самого класса
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.10.2016, 12:16 8
Цитата Сообщение от sys_beginner Посмотреть сообщение
А можно указывать присвоение значения полю внутри класса не вне него?
Раньше нельзя было, в С++11 не знаю.

Можно еще так:
C++
1
2
3
4
5
6
7
const std::string& getValue(int i,const std::string& defaultValue= std::string()) const
{
   std::map<int,std::string>::iterator it= m.find(i);
   if(it!=m.end())
     return it->second;
   return  defaultValue;
}
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
06.10.2016, 12:17 9
Цитата Сообщение от sys_beginner Посмотреть сообщение
У меня ключи должны идти не последовательно
1) Ключём может быть любой тип у которого определён оператор меньше. С этим справитесь?)
Цитата Сообщение от sys_beginner Посмотреть сообщение
например 500, 700
2) Смысл enum class как раз в том, чтобы не заморачиватся с значениями в голове - поменяете вы 500 на 522, вы что по всему коду будете лазить искать getSome( 500 ) ? Почитайте что такое enum class еще раз - очень часто enum class не нуждается в значениях - так как они излишни.

Добавлено через 30 секунд

Не по теме:

Цитата Сообщение от Max Dark Посмотреть сообщение
ух. пока я тут калякал сколько уже понаписали))
стареете?)

0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.10.2016, 12:19 10
Цитата Сообщение от sys_beginner Посмотреть сообщение
роль ассоциативного массива?
Можно использовать хеш таблицу http://ru.cppreference.com/w/c... rdered_map
0
882 / 467 / 92
Регистрация: 10.06.2014
Сообщений: 2,676
06.10.2016, 12:24  [ТС] 11
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Ключём может быть любой тип у которого определён оператор меньше. С этим справитесь?)
Оператор меньше? Не понял о каком операторе идет речь и меньше чего он должен быть

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Смысл enum class как раз в том, чтобы не заморачиватся с значениями в голове
Я понимаю, но мне нужно не совсем это. Мне нужен статичный константный ассоциативный массив внутри класса с целочисленными ключами. А вот для обращений к ключам - да, здесь enum отлично подойдет, но в данный момент речь не об этом

Цитата Сообщение от Avazart Посмотреть сообщение
Можно использовать хеш таблицу
А она оптимальнее чем map?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.10.2016, 12:27 12
Цитата Сообщение от sys_beginner Посмотреть сообщение
А она оптимальнее чем map?
В данном случае думаю да.
0
882 / 467 / 92
Регистрация: 10.06.2014
Сообщений: 2,676
06.10.2016, 12:31  [ТС] 13
Цитата Сообщение от Avazart Посмотреть сообщение
В данном случае думаю да.
А чем именно и как это можно проверить?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.10.2016, 12:36 14
https://blog.dshevchenko.biz/2... tdmap.html
1
882 / 467 / 92
Регистрация: 10.06.2014
Сообщений: 2,676
06.10.2016, 12:39  [ТС] 15
Avazart,
Благодарю за ссылку

Добавлено через 16 секунд
А чем такая разница в скорости объясняется?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.10.2016, 12:51 16
http://230100.msiu.ru/files/48... ultimapc11
0
882 / 467 / 92
Регистрация: 10.06.2014
Сообщений: 2,676
06.10.2016, 15:32  [ТС] 17
Avazart,
Склеил ваши предложения и вот что получилось
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
#include <iostream>
#include <string>
#include <unordered_map>
 
class X
{
    public:
        const std::string& getValue(int i) const
        {
            return m.at(i); 
        }
    enum Indexes
   {
      THREE = 3,
      SIX = 6
   };
    
    private:
        static const std::unordered_map<int,std::string> m;
};
  
 
const std::unordered_map<int,std::string> X::m = { {3, "three"}, {6, "six"}}; 
 
int main()
{
  X x;
  std::cout << x.getValue(X::Indexes::THREE);
  return 0;
}
Я все нормально сделал? В частности интересно про enum. Он статичен по умолчанию и при создании нового экземпляра под него не будет повторно выделяться память или будет?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.10.2016, 15:44 18
Не совсем, если использовать то уж везде и по возможности enum class.
C++
1
2
3
4
5
6
7
8
 enum class Index
   {
      three = 3,
      six = 6
   };
 
const std::unordered_map<int,std::string> 
      X::m = { {Index::tree, "three"}, {Index::six, "six"}};
Добавлено через 5 минут
Да и еще
C++
1
2
3
4
const std::string& getValue(Index index) const
{
   return m.at(index); 
}
0
882 / 467 / 92
Регистрация: 10.06.2014
Сообщений: 2,676
06.10.2016, 15:59  [ТС] 19
Цитата Сообщение от Avazart Посмотреть сообщение
Не совсем, если использовать то уж везде и по возможности enum class.
"Не совсем" это всмысле вы про память или про то правильно ли сделал?
Дело в том что эти индексы относятся именно к классу, а внутри класса уже писать { {Indexes::THREE, "three"}, {Indexes:SIX, "six"}}. В связи с этим не очень понимаю зачем их надо оформлять отдельно. И ещё не понял почему после enum нужно писать слово class когда можно просто enum? Что бы можно было от его имени к константам обращаться?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.10.2016, 16:17 20
Цитата Сообщение от sys_beginner Посмотреть сообщение
И ещё не понял почему после enum нужно писать слово class когда можно просто enum? Что бы можно было от его имени к константам обращаться?
https://ru.wikipedia.org/wiki/... 0.B5.D0.B9

Цитата Сообщение от sys_beginner Посмотреть сообщение
"Не совсем" это всмысле вы про память или про то правильно ли сделал?
Про то что бы избавится от магических чисел и int заменить enum class Index везде.
0
06.10.2016, 16:17
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.10.2016, 16:17
Помогаю со студенческими работами здесь

Константный метод изменяет поля класса
Объясните, пожалуйста, почему такой код компилируется и работает без ошибок. И что нужно сделать в...

Константный метод и константный аргумент в методе
Товарищи! Возник вопрос, в чем же разница, между константным методом и ссылкой на const объект в...

Массив как поле класса
Например, имеется класс с полем массивом размерностью 10 на 10. class massiv { private: int mas;...

Поле класса - динамический массив
Здравствуйте, друзья. Проверьте, пожалуйста, всё ли правильно написано (отсутствие сообщений об...


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

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

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