На данный момент в нашем программном продукте при описании свойств объекта используется:
typedef struct tobj_status_bit
{
unsigned Sts : 1; // 0 состояние объекта: 1 — в работе; 0 — выключен
unsigned Rdy : 1; // 1 готовность объекта: 1 — есть; 0 -нет
} TObj_Status_Bit;
typedef union tobj_status
{
TObj_Status_Bit bReg; // побитное представление
unsigned int Reg; // регистровое представление
} TObj_Status;
Хотелось бы:
class CObj_Status
{
..
TObj_Status dObj_Status;
..
};
CObj_Status Obj_Status;
и при присвоении полю структуры какого-то значения выполнить еще ряд действий, т.е.:
Obj_Status.dObj_Status.bReg.Sts = 1 или
Obj_Status.dObj_Status.bReg.Rdy = 1
приводило к выполнению кода:
{
// действия
dObj_Status.bReg.Sts = 1;
}
Здравствуйте, bookevg, Вы писали:
B>CObj_Status Obj_Status; B>и при присвоении полю структуры какого-то значения выполнить еще ряд действий, т.е.: B>Obj_Status.dObj_Status.bReg.Sts = 1 или B>Obj_Status.dObj_Status.bReg.Rdy = 1 B>приводило к выполнению кода: B>{ B>// действия B>dObj_Status.bReg.Sts = 1; B>}
тоесть Вы properties хотите, проще говоря ?
некоторые компиляторы их поддерживают на уровне расширений.
но ведь можно и метод сделать
class CObj_Status
{
void SetBit( unsigned bit ) { /* тут все нужные действия */ }
};
Здравствуйте, _Dreamer, Вы писали:
_D>Здравствуйте, bookevg, Вы писали:
B>>CObj_Status Obj_Status; B>>и при присвоении полю структуры какого-то значения выполнить еще ряд действий, т.е.: B>>Obj_Status.dObj_Status.bReg.Sts = 1 или B>>Obj_Status.dObj_Status.bReg.Rdy = 1 B>>приводило к выполнению кода: B>>{ B>>// действия B>>dObj_Status.bReg.Sts = 1; B>>}
_D>тоесть Вы properties хотите, проще говоря ? _D>некоторые компиляторы их поддерживают на уровне расширений. _D>но ведь можно и метод сделать _D>
_D>class CObj_Status
_D>{
_D> void SetBit( unsigned bit ) { /* тут все нужные действия */ }
_D>};
_D>
_D>?
Да хотелось бы реализовать свойства — но только без использования расширений компилятора — при этом не хотелось бы для каждого битового поля писать методы
Здравствуйте, Seon, Вы писали:
S>Здравствуйте, bookevg, Вы писали:
B>>На данный момент в нашем программном продукте при описании свойств объекта используется: B>>typedef struct tobj_status_bit B>>{ B>> unsigned Sts : 1; // 0 состояние объекта: 1 — в работе; 0 — выключен B>> unsigned Rdy : 1; // 1 готовность объекта: 1 — есть; 0 -нет B>>} TObj_Status_Bit; B>>typedef union tobj_status B>>{ B>> TObj_Status_Bit bReg; // побитное представление B>> unsigned int Reg; // регистровое представление B>>} TObj_Status; B>>Хотелось бы: B>>class CObj_Status B>>{ B>>.. B>>TObj_Status dObj_Status; B>>.. B>>}; B>>CObj_Status Obj_Status; B>>и при присвоении полю структуры какого-то значения выполнить еще ряд действий, т.е.: B>>Obj_Status.dObj_Status.bReg.Sts = 1 или B>>Obj_Status.dObj_Status.bReg.Rdy = 1 B>>приводило к выполнению кода: B>>{ B>>// действия B>>dObj_Status.bReg.Sts = 1; B>>}
S>для чтения / записи данных в структуру используй методы S>typedef struct tobj_status_bit S>{ S> unsigned Sts : 1; // 0 состояние объекта: 1 — в работе; 0 — выключен S> unsigned Rdy : 1; // 1 готовность объекта: 1 — есть; 0 -нет
S> void set_sts(unsigned st) {Sts = st; /*И еще чтото*/} S> unsigned sts() const {return Sts; /*И еще чтото*/} S>} TObj_Status_Bit;
S>и так далее...
Но тогда для каждого битового поля необходимо будет написать методы чтения/записи, а в коде все править — вместо простого присвоения/чтения элемента структуры надо реализовать вызов.
Т.о. необходимо: переопределить оператор присваивания структуры, но как определить какое битовое поле необходимо изменять/читать?
Здравствуйте, bookevg, Вы писали:
B>Но тогда для каждого битового поля необходимо будет написать методы чтения/записи, а в коде все править — вместо простого присвоения/чтения элемента структуры надо реализовать вызов.
Ну можно создать для каждого при необходимости, и можно сделать общую функцию для всех битов.
void set_bits(unsigned bits, unsigned mask = 0xffffffff);
и при пользовании этой функции определить в какой бите числа что находится.
а еще лучче
void set(const tobj_status_bit& bt);
B>Т.о. необходимо: переопределить оператор присваивания структуры, но как определить какое битовое поле необходимо изменять/читать?
М>Можно завести вспомогательные классы, правда тогда регистровое представление функцией нужно сделать (у меня так получилось, но возможны варианты).
Ага, можно аналогичный класс и интерфейс завести (Reg/ireg).
Здравствуйте, Максим2006, Вы писали:
М>Здравствуйте, bookevg, Вы писали:
М>Можно завести вспомогательные классы, правда тогда регистровое представление функцией нужно сделать (у меня так получилось, но возможны варианты).
Вроде все получается, но вот только расход памяти большой: для 16=тиразрядного числа: 16 * 4байта * 4указателя(при 32-хразрядных указателях) + 2байта (само число) = 258 — для моего арм-процессора это много. Таких регистров м.б. 250 штук.
Здравствуйте, Максим2006, Вы писали:
М>Здравствуйте, Максим2006, Вы писали:
М>>Можно завести вспомогательные классы, правда тогда регистровое представление функцией нужно сделать (у меня так получилось, но возможны варианты). М>Ага, можно аналогичный класс и интерфейс завести (Reg/ireg).
Здравствуйте, bookevg, Вы писали:
B>Здравствуйте, Максим2006, Вы писали:
М>>Здравствуйте, bookevg, Вы писали:
М>>Можно завести вспомогательные классы, правда тогда регистровое представление функцией нужно сделать (у меня так получилось, но возможны варианты).
B>Вроде все получается, но вот только расход памяти большой: для 16=тиразрядного числа: 16 * 4байта * 4указателя(при 32-хразрядных указателях) + 2байта (само число) = 258 — для моего арм-процессора это много. Таких регистров м.б. 250 штук.
Это ведь непрямой путь к цели. Тут неизбежны накладные расходы. Прямой путь — это ввод методов по установке флагов. Кое-что можно перенести на рантайм, но это уже хаки по-любому.
Здравствуйте, Максим2006, Вы писали:
М>Здравствуйте, bookevg, Вы писали:
B>>Здравствуйте, Максим2006, Вы писали:
М>>>Здравствуйте, bookevg, Вы писали:
М>>>Можно завести вспомогательные классы, правда тогда регистровое представление функцией нужно сделать (у меня так получилось, но возможны варианты).
B>>Вроде все получается, но вот только расход памяти большой: для 16=тиразрядного числа: 16 * 4байта * 4указателя(при 32-хразрядных указателях) + 2байта (само число) = 258 — для моего арм-процессора это много. Таких регистров м.б. 250 штук.
М>Это ведь непрямой путь к цели. Тут неизбежны накладные расходы. Прямой путь — это ввод методов по установке флагов. Кое-что можно перенести на рантайм, но это уже хаки по-любому. М>
М> struct StatusData
М> {
М> private:
М> void SetStatus(unsigned status) { m_DataUnion.dataBit.nStatus = status; }
М> unsigned GetStatus() { return m_DataUnion.dataBit.nStatus; }
...
М> private:
М> struct StatusField
М> {
М> void operator=(unsigned ready) { pThis()->SetStatus(ready); }
М> operator unsigned() { return pThis()->GetStatus(); }
М> private:
М> StatusData* pThis() {
М> StatusField StatusData::* pmem = &StatusData::Status;
М> return (StatusData*)((__int64)(this) - *(__int64*)&pmem);
М> }
М> };
У меня арм-процессор с 32разр.шиной, посему поменял __int64 на __int32, при этом не работает доступ к элементам
...
М> };
М>
Здравствуйте, bookevg, Вы писали:
B>У меня арм-процессор с 32разр.шиной, посему поменял __int64 на __int32, при этом не работает доступ к элементам
Скорее всего это из-за разных компиляторов. Я использовал VC++. Хак основан на том, что в этих компиляторах от MS указатель на мембер является смещением относительно this самого класса. У меня эти смещения, в нашем примере, для мемберов Status, Ready и Reg равны соответственно 0, 1 и 2. Скорее всего, в Вашем компиляторе это не так, поэтому pThis() возвращает неправильный адрес. Поэкспериментируйте, идея, я думаю, ясна.
Здравствуйте, Максим2006, Вы писали:
М>Здравствуйте, bookevg, Вы писали:
B>>У меня арм-процессор с 32разр.шиной, посему поменял __int64 на __int32, при этом не работает доступ к элементам М>Скорее всего это из-за разных компиляторов. Я использовал VC++. Хак основан на том, что в этих компиляторах от MS указатель на мембер является смещением относительно this самого класса. У меня эти смещения, в нашем примере, для мемберов Status, Ready и Reg равны соответственно 0, 1 и 2. Скорее всего, в Вашем компиляторе это не так, поэтому pThis() возвращает неправильный адрес. Поэкспериментируйте, идея, я думаю, ясна.
А есть ли другой более элегатный способ получить указатель на StatusData, не зависящий от свойств компилятора?
Здравствуйте, Максим2006, Вы писали:
М>Здравствуйте, bookevg, Вы писали:
B>>Здравствуйте, Максим2006, Вы писали:
М>>>Здравствуйте, bookevg, Вы писали:
М>Это ведь непрямой путь к цели. Тут неизбежны накладные расходы. Прямой путь — это ввод методов по установке флагов. Кое-что можно перенести на рантайм, но это уже хаки по-любому. М>
Можно ли создать шаблон, который бы мог менять имена полей Status, Ready, Reg.
Т.е. описываем шаблон на базе данного примера, при этом имена struct Data безымянные (что-то типа bit0, bit1 и т.п.) и имена public-структур-полей безыменные: Bit0Field, Bit1Field, но имена переменных, должны быть определены каким-то образом — м.б. разными. Т.о. не надо описывать структуру каждый раз при изменении имен полей
Здравствуйте, bookevg, Вы писали:
B>Здравствуйте, Максим2006, Вы писали:
М>>Здравствуйте, bookevg, Вы писали:
B>>>У меня арм-процессор с 32разр.шиной, посему поменял __int64 на __int32, при этом не работает доступ к элементам М>>Скорее всего это из-за разных компиляторов. Я использовал VC++. Хак основан на том, что в этих компиляторах от MS указатель на мембер является смещением относительно this самого класса. У меня эти смещения, в нашем примере, для мемберов Status, Ready и Reg равны соответственно 0, 1 и 2. Скорее всего, в Вашем компиляторе это не так, поэтому pThis() возвращает неправильный адрес. Поэкспериментируйте, идея, я думаю, ясна.
B>А есть ли другой более элегатный способ получить указатель на StatusData, не зависящий от свойств компилятора?
Так чтоб на рантайме находить this нужного объекта, не знаю. Если узнаете, поделитесь обязательно
Здравствуйте, bookevg, Вы писали:
B>Можно ли создать шаблон, который бы мог менять имена полей Status, Ready, Reg. B>Т.е. описываем шаблон на базе данного примера, при этом имена struct Data безымянные (что-то типа bit0, bit1 и т.п.) и имена public-структур-полей безыменные: Bit0Field, Bit1Field, но имена переменных, должны быть определены каким-то образом — м.б. разными. Т.о. не надо описывать структуру каждый раз при изменении имен полей
А зачем это? Объясните на примере.
Здравствуйте, Максим2006, Вы писали:
М>Здравствуйте, bookevg, Вы писали:
B>>Можно ли создать шаблон, который бы мог менять имена полей Status, Ready, Reg. B>>Т.е. описываем шаблон на базе данного примера, при этом имена struct Data безымянные (что-то типа bit0, bit1 и т.п.) и имена public-структур-полей безыменные: Bit0Field, Bit1Field, но имена переменных, должны быть определены каким-то образом — м.б. разными. Т.о. не надо описывать структуру каждый раз при изменении имен полей М>А зачем это? Объясните на примере.
С примером трудновато, попробую словами:
есть некий макрос, который описывает вышеприведенный класс, за исключением того, что:
имена Status, Ready, Reg м.б. заданы любые, т.о. данный макрос можно использовать при создании класса у которого взамен имен Status, Ready будет Pusk, Stop и тогда не требуется переписывать класс при изменении имен параметров Status, Ready, хотя тип остается такой же
Здравствуйте, bookevg, Вы писали:
B>есть некий макрос, который описывает вышеприведенный класс, за исключением того, что: B>имена Status, Ready, Reg м.б. заданы любые, т.о. данный макрос можно использовать при создании класса у которого взамен имен Status, Ready будет Pusk, Stop и тогда не требуется переписывать класс при изменении имен параметров Status, Ready, хотя тип остается такой же
Так что ли?
#define CLASS_TEMPLATE(name, var1, var2) struct name { int var1; int var2; };
Подозреваю, что Вы собираетесь либо описать одну и ту же сущность разными типами, либо разные сущности — одним. И то и другое — ошибка дизайна, которая впоследствии может вылезти боком.
Здравствуйте, Максим2006, Вы писали:
М>Здравствуйте, bookevg, Вы писали:
B>>есть некий макрос, который описывает вышеприведенный класс, за исключением того, что: B>>имена Status, Ready, Reg м.б. заданы любые, т.о. данный макрос можно использовать при создании класса у которого взамен имен Status, Ready будет Pusk, Stop и тогда не требуется переписывать класс при изменении имен параметров Status, Ready, хотя тип остается такой же
М>Так что ли? М>
М>#define CLASS_TEMPLATE(name, var1, var2) struct name { int var1; int var2; };
М>
Что-то в этом роде.
М>Подозреваю, что Вы собираетесь либо описать одну и ту же сущность разными типами, либо разные сущности — одним. И то и другое — ошибка дизайна, которая впоследствии может вылезти боком.
Сущность носит названия регистр-сигналов. В зависимости от предназначения его битовые поля могут называться по разному, но методы работы с полями одни и те же. В идеале можно было бы использовать структуры битовых полей (ЧТО СЕЙЧАС И ЕСТЬ), но необходиом осущесвить ряд действий при изменении битового поля — например, зафиксировать факт изменения поля — на этом основан принцип организации событийности системе управления