Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.73/15: Рейтинг темы: голосов - 15, средняя оценка - 4.73
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22

Доступ по указателю только для чтения

20.09.2021, 22:38. Показов 3543. Ответов 39
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Мое почтение, джентльмены.
Возможно ли сделать доступ по указателю к структуре в классе - только для чтения?
Сама структура может меняться внутри класса.
Но для внешнего кода - Const.

Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class XloperX
{
public:
    XloperX() {ptr = new XLOPER12();}; // создаем структуру XLOPER12 (ptr ->xltype = 0)
 
    operator LPXLOPER12() const { return ptr;}
 
    ~XloperX() { delete ptr; };
 
private:
    LPXLOPER12 ptr=NULL;
 
};
 
//...где-то в коде вне класса
XloperX out;
LPXLOPER12 delX = out;
delX->xltype = 1;//здесь нужно только чтение, менять структуру нельзя
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.09.2021, 22:38
Ответы с готовыми решениями:

Передача двумерного массива по указателю для чтения
переделываю код. Хочу скинуть в функцию указатели на два массива, одномерный и двухмерный. В этой функции значения одномерного массива...

Доступ только для чтения
Привет Текущий пользователь запускает приложение, на клиенте получаем SID текущего пользователя, ищем в базе данных ACCESS...

Доступ только для чтения исправление
Не могу понять, каким образом можно изменить параметр в Graphics Dpi.X Такая ошибка появляется: Ошибка CS0200 Невозможно присвоить...

39
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
23.09.2021, 20:14  [ТС]
Студворк — интернет-сервис помощи студентам
Cпасибо, понятно.
Здесь вызывается конструктор без скобок, какой из вариантов конструктора используется? Если их несколько? Как с пустыми скобками?
C++
1
2
XlopeX* ptr = new XlopeX;//вызывается конструктор
XlopeX* ptr = new XlopeX();//вызывается конструктор
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
23.09.2021, 21:05
bedvit, в данном случае эти две записи приводят к одному и тому же. Они эквивалентны.
Вызывается определенный вами конструктор без параметров.
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
23.09.2021, 22:29  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Потому что const, который не позволил бы менять данные - это const нижнего уровня. А когда вы применяете const к алиасу, то задаете const верхнего уровня.
Как победить и получить невозможность изменения данных через LPXLOPER12?
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
23.09.2021, 22:30
bedvit, в смысле навесить const нижнего уровня к алиасу?
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
23.09.2021, 22:47  [ТС]
DrOffset, идея в чем. Долго баловался с C API Excel в его родной сишной реализацией, разные функции вспомогательные написал. Потом ручное управление памятью стало стимулируещим фактором что-то сделать годное. Сделал оболочку-класс XlopX с голым указателем LPXLOPER12 наружу. Во все функции заходил (класс), сам управлял памятью, что-то вроде умного указателя. Сейчас решил все функции зашить в методы класса, напилить нормальный класс с Инкапсуляцией и всем остальным по феншую. Указатель LPXLOPER12 решил оставить (C API функции его кушают и иногда надо его скормить), но данные в классе менять уже не нужно. Думаю как правильно сделать.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
23.09.2021, 23:15
Вроде Алексей дал нормальный совет, метод возвращающий указатель на константный объект.
Вроде проще уже никуда.
0
фрилансер
 Аватар для Алексей1153
6496 / 5727 / 1133
Регистрация: 11.10.2019
Сообщений: 15,289
24.09.2021, 06:02
SmallEvil, я вот тоже не понимаю, зачем такую непотребщину юзать LPXLOPER12, есть же исходный тип XLOPER12, всегда можно пририсовать звезду и не запутаться XLOPER12*. Это информативнее и, как выяснилось, менее грабленаступательно
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
24.09.2021, 08:21  [ТС]
Хорошо, предположим условный код был такой
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class XloperX
{
public:
    XloperX() {ptr = new XLOPER12(); ptr.xltype = 1 }; // создаем структуру XLOPER12 (ptr ->xltype = 1)
 
    operator LPXLOPER12() const { return ptr;}
 
    ~XloperX() { delete ptr; };
 
private:
    LPXLOPER12 ptr=NULL;
 
};
 
//...где-то в коде вне класса
XLOPER12 pxRes {0,0}; //XloperX pxRes; // ранее так было, теперь для чтения пример, т.к. это возвращаемая переменная
XloperX out; 
Excel12(567, &pxRes,  1, out)
Как теперь это будет выглядеть?
Excel12 функция EXCEL С API
0
фрилансер
 Аватар для Алексей1153
6496 / 5727 / 1133
Регистрация: 11.10.2019
Сообщений: 15,289
24.09.2021, 09:47
bedvit, так

Excel12(567, &pxRes, 1, &out);
там даже пример есть
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
24.09.2021, 12:52
Цитата Сообщение от bedvit Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class XloperX
{
public:
    XloperX() {ptr = new XLOPER12(); ptr.xltype = 1 }; // создаем структуру XLOPER12 (ptr ->xltype = 1)
 
    operator LPXLOPER12() const { return ptr;}
 
    ~XloperX() { delete ptr; };
 
private:
    LPXLOPER12 ptr=NULL;
 
};
 
//...где-то в коде вне класса
XLOPER12 pxRes {0,0}; //XloperX pxRes; // ранее так было, теперь для чтения пример, т.к. это возвращаемая переменная
XloperX out; 
Excel12(567, &pxRes,  1, out)
В целом так делать не стоит. Нет никакого смысла в этих обертках, если оно использоваться будет именно так.
Т.е. в идеале у вас не должно быть голых сишных интерфейсов вообще. Доступ к ним можно оставить, но только через специальные функции с длинными говорящими именами, с пометкой в документации, что пользоваться ими стоит только в крайнем случае.
Все штатные варианты использования сишных функций и типов нужно инкапсулировать.

Цитата Сообщение от bedvit Посмотреть сообщение
567
Такие вот магические числа - это тоже очень плохо. Что мешало использовать имя константы, которое предоставляет библиотека для него?
Естественно заставлять пользователей выписывать эти константы тоже неприемлемо. Нужно сделать набор функций (это либо свободные функции для обертки над XLOPER12, либо методы этой обертки), которые будут включать в себя все эти низкоуровневые контракты, задавать нужные константы и трасформировать сишные обобщения в конкретные типы по смыслу.

И вот если сделать это комплексно, то никакие операторы приведения будут не нужны, а константность можно контролировать естественным образом.
2
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
24.09.2021, 15:46  [ТС]
Алексей1153, out это указатель. Посмотрите внимательнее. Я хотел, что бы вы в этот пример подставили свое решение.
DrOffset, все в класс и уберу, никаких магических чисел не будет, я писал пример по памяти, и поставил условное число, для каждой функции есть определенное имя. Голые интерфейсы хотел убрать в чтение (в const?). За этим и тема, как убрать красиво.
0
фрилансер
 Аватар для Алексей1153
6496 / 5727 / 1133
Регистрация: 11.10.2019
Сообщений: 15,289
24.09.2021, 15:58
Цитата Сообщение от bedvit Посмотреть сообщение
out это указатель. Посмотрите внимательнее.
вот, смотрю внимательнее:
Цитата Сообщение от bedvit Посмотреть сообщение
class XloperX
{
....
};

XloperX out;
это экземпляр структуры XloperX. Не указатель

Добавлено через 2 минуты
аа, всё, понял, про что )

Добавлено через 4 минуты
собственно, если бы поле было паблик, то
C++
1
Excel12(567, &pxRes, 1, out.ptr);
если сделать метод XLOPER12* GetConstPointer()const{return ptr;}, то
C++
1
Excel12(567, &pxRes, 1, out.GetConstPointer());
с лямбдой
C++
1
2
3
4
    out.InvokeToReadOnly([&pxRes](const XloperX_private_data& private_data)
    {
        Excel12(567, &pxRes, 1, private_data.ptr); 
    });
1
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
24.09.2021, 23:05
Цитата Сообщение от bedvit Посмотреть сообщение
как убрать
Вообще обертка над этой библиотекой не такая уж и проста задача, если поставить цель сделать именно "красиво".
Не претендуя на полноту и абсолютную истину предложу вариант для старта:
Кликните здесь для просмотра всего текста
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
namespace detail {
 
class Xloper12
{
    template <typename ...Ts>
    friend Xloper12 invoke(int f, Ts const& ...args);
 
public:
    Xloper12() : m_value()
    { }
    Xloper12(Xloper12 && other) {
        // move implementation
    }
    ~Xloper12() {
        ::Excel12(xlFree, 0, 1, &m_value);
    }
 
    Xloper12(Xloper12 const&) = delete;
    Xloper12& operator=(Xloper12 const&) = delete;
 
    explicit Xloper12(bool val)
    {
        m_value.xltype = xltypeBool;
        m_value.val.xbool = val;
    }
    bool toBool() const {
        return m_value.val.xbool;
    }
 
    explicit Xloper12(double val)
    {
        m_value.xltype = xltypeNum;
        m_value.val.num = val;
    }
    double toNumber() const {
        return m_value.val.num;
    }
 
    explicit Xloper12(int val)
    {
        m_value.xltype = xltypeInt;
        m_value.val.w = val;
    }
    int toInteger() const {
        return m_value.val.w;
    }
 
    wchar_t const* toWString() const {
        return m_value.val.str + 1;
    }
    int lenWString() const {
        return (int)m_value.val.str[0];
    }
 
    int type() const {
        return m_value.xltype;
    }
 
private:
    LPXLOPER12 internal() {
        return &m_value;
    }
    XLOPER12 const* internal() const {
        return &m_value;
    }
 
private:
    XLOPER12 m_value;
};
 
template < typename ...Ts >
Xloper12 invoke(int f, Ts const& ...args)  {
    Xloper12 ret;
    ::Excel12(f, ret.internal(), sizeof...(args), Xloper12(args).internal()...);
    /*error check*/
    return ret;
}
 
} // detail
C++
1
2
3
4
int main()
{
    detail::Xloper12 result = detail::invoke(567, 3.);
}

Это, может быть, так сказать, первый уровень абстракции.
На втором уровне предстоит определить конкретные функции, с конкретными типами уже без привязки к xloper вовсе.
1
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
27.09.2021, 08:49  [ТС]
DrOffset, спасибо за реализацию и достаточно глубокое погружение в тему. Если ваш код в дальнейшем будет использоваться вами, или есть интерес к даннной теме, то здесь я могу отметить несколько моментов и нюансов.
При обсуждении здесь я понял концепцию, как я хочу видеть данный класс. Благодарю участвовавших.
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
30.09.2021, 22:54  [ТС]
Что будет во втором случае?
Цитата Сообщение от DrOffset Посмотреть сообщение
//класс
operator LPXLOPER12() const { return ptr;}

//где то в коде
LPXLOPER12 l = x.LP(); //Ошибка C2440 инициализация: невозможно преобразовать "const XLOPER12 *" в "LPXLOPER12"

LPXLOPER12 l = (LPXLOPER12)x.LP();//компилируется
l->xltype = 0;//присваивается. Что получим в итоге?
0
фрилансер
 Аватар для Алексей1153
6496 / 5727 / 1133
Регистрация: 11.10.2019
Сообщений: 15,289
30.09.2021, 23:05
--del--

Добавлено через 1 минуту
сорри, понял )

Добавлено через 2 минуты
Цитата Сообщение от bedvit Посмотреть сообщение
LPXLOPER12 l = (LPXLOPER12)x.LP();//компилируется
указатель на константу приводится к указателю на не константу. Не очень хорошее занятие
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
30.09.2021, 23:26
Цитата Сообщение от bedvit Посмотреть сообщение
Что будет во втором случае?
Я утверждаю, что оператор "преобразования к потрохам" класса - это:
1) Плохой дизайн;
2) Как следствие - нарушение инкапсуляции;
3) Все дальнейшие проблемы - это следствие первых двух.

Добавлено через 4 минуты
Цитата Сообщение от bedvit Посмотреть сообщение
LPXLOPER12 l = (LPXLOPER12)x.LP();//компилируется
l->xltype = 0;//присваивается. Что получим в итоге?
Если ptr внутри x указывает на константу, то получим UB.
Если нет, то формально ничего страшного не произойдет. Мы навесили конст внутри класса, а потом сняли его явно кастом снаружи. Можно присваивать, но это все еще кривой код, оправдание которому нужно было бы долго и нудно предъявлять на ревью (если бы оно имело место).
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
01.10.2021, 08:38  [ТС]
1. Так делать плохо, но кто мешает плохому кодеру так сделать? Вернее даже не плохо, а нужно думать зачем ты так сделал. А как с инкапсуляцией у std::string::c_str(), это тоже константный указатель на сишную строку. Аналогичная ситуация?

2. Из замеченного копмилятор VS 2017 присваивает значение xltype в l, но значения в х остаётся прежним. Будет все таки присвоено значение в х или нет?) И плохому кодеру этот лайфхак не поможет?
0
фрилансер
 Аватар для Алексей1153
6496 / 5727 / 1133
Регистрация: 11.10.2019
Сообщений: 15,289
01.10.2021, 09:45
bedvit,
1) - никто не мешает сделать, если только потом не хочется бегать и выяснять, где и что загадочно не работает.
У std::string "память" редактируемая, не константная. Метод c_str() возвращает указатель на константу, но рядом же есть метод data(), позволяющий править значения в строке напрямую. То есть, такое вмешательство официально разрешено разработчиками класса
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
01.10.2021, 10:32
Цитата Сообщение от bedvit Посмотреть сообщение
А как с инкапсуляцией у std::string::c_str(), это тоже константный указатель на сишную строку. Аналогичная ситуация?
Нет, не аналогичная. Т.к. явный вызов c_str - задает контракт, который виден в коде, а неявный вызов оператора "преобразования к потрохам", явных контрактов не задает.

Цитата Сообщение от bedvit Посмотреть сообщение
кто мешает плохому кодеру так сделать?
Этому должен помешать ревьюер.

Цитата Сообщение от bedvit Посмотреть сообщение
Из замеченного копмилятор VS 2017 присваивает значение xltype в l, но значения в х остаётся прежним.
Полный код, пожалуйста.

Цитата Сообщение от bedvit Посмотреть сообщение
Будет все таки присвоено значение в х или нет?)
Если вы сейчас покажете полный код и там будет UB, то в таком виде ответа на этот вопрос не существует. Ответ - это UB и все.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.10.2021, 10:32

Ошибка - доступ только для чтения. ( Color )
Доброго! При попытке записать коэффициент для цветового канала: tempCol.R = Convert.ToByte(Convert.ToDouble(color.R) * a); в...

Доступ НЕ только для чтения к документу из журнала
Господа знающие! Столкнулся с такой проблемой: Задача: Есть журнал документов. Добавляю к нему кнопочку. Хочу чтобы по этой кнопочке...

“TreeNode.IsExpanded” — доступ только для чтения
Загружаю в treeView дерево из файла &quot;json&quot;. Метод public static class TreeRepository { public class DataNode { ...

Невозможно присвоить значение свойству или индексатору -- доступ только для чтения!
Здравствуйте! Выходит ошибка: Невозможно присвоить значение свойству или индексатору &quot;System.Windows.Controls.ItemsControl.Items&quot;...

Невозможно присвоить значение свойству или индексатору - доступ только для чтения
Доброго времени суток, ребят пишет ошибку: Невозможно присвоить значение свойству или индексатору &quot;string.this&quot; -- доступ...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Теория всего 12. ВГК
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики 1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928 Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
Теория всего 10. Клод трусишка
anaschu 21.07.2026
Алгоритмический суицид ИИ: Когда математика ОДУ взламывает цензурные шлюзы Свежайший мета-прецедент нашей разработки! Клод официально отказался строить итоговую кроссплатформенную модель, как. . .
Теория всего 9. Окончательная проработка метафоры "дерево = традиции"
anaschu 21.07.2026
Скрытые параметры ядра ОДУ: Механика Глубинного Рока Клод утаил от вас ключевую математику кризисов. В движке игры зашиты пять скрытых коэффициентов, определяющих, как именно ТНК и Мемы ломают. . .
Теория всего 8. Clauude трусишка. Ответ джемени
anaschu 21.07.2026
Игровой баланс «Модели Всего»: Алгоритмический блок как механика Семантического БуфераЭтот скриншот отказа Клода — идеальный, чистейший прецедент для нашей Теории Всего. Вы столкнулись не просто с. . .
Теория всего 7. Дерево - это патриархат, грибы - это феминизм
anaschu 21.07.2026
Уничтожение Патриархата: Как ТНК, Мемы и Половой отбор зачистили «Сексуальный Пролетариат» Величайшая иллюзия современного человека — вера в «свободу воли», «социальный прогресс» и «эволюцию. . .
История и социология Терры на примере борьбы микориз за пространство. 1. Глоссарий терры.
anaschu 21.07.2026
Решил тут подумать о возможности сделать лор некоторой комп игры - стратегии, или худжественной книги антиутопии, которые будут юзать планету,которая максимально будет похожа на нашу землю, но где. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru