Не подскажите как правильно перегрузить преобразование к типу int/unsigned? Например есть код:
class VRGB
{
public:
// Красная компонентаunsigned char r;
// Зеленая компонентаunsigned char g;
// Голубая компонентаunsigned char b;
// Альфа-составляющаяunsigned char a;
public:
// Перегрузка при ведения к типу intoperator int(){return *((int*)this);}
// Конструктор для типа int
VRGB(int Integer){ *((int*)this) = Integer; }
}
void SomeAction(int SomeValue)
{
...
}
int main()
{
int a;
VRGB b;
b = a;
a = b;
SomeAction(b);
}
Класс VRGB занимает 4 байта, ровно столько сколько занимает переменная типа int. Я правильно написал перегрузку? Будет ли работать код корректно если переменная b, будет хранится, например, в регистре? Или надо писать код перегрузки приведения по-другому?
Здравствуйте, PavelCH, Вы писали:
PCH>Здраствуйте все.
PCH>Не подскажите как правильно перегрузить преобразование к типу int/unsigned? Например есть код:
PCH>
PCH>class VRGB
PCH>{
PCH>public:
PCH> // Красная компонента
PCH> unsigned char r;
PCH> // Зеленая компонента
PCH> unsigned char g;
PCH> // Голубая компонента
PCH> unsigned char b;
PCH> // Альфа-составляющая
PCH> unsigned char a;
PCH>public:
PCH> // Перегрузка при ведения к типу int
PCH> operator int(){return *((int*)this);}
PCH> // Конструктор для типа int
PCH> VRGB(int Integer){ *((int*)this) = Integer; }
PCH>}
PCH>void SomeAction(int SomeValue)
PCH>{
PCH>...
PCH>}
PCH>int main()
PCH>{
PCH> int a;
PCH> VRGB b;
PCH> b = a;
PCH> a = b;
PCH> SomeAction(b);
PCH>}
PCH>
PCH>Класс VRGB занимает 4 байта, ровно столько сколько занимает переменная типа int. Я правильно написал перегрузку? Будет ли работать код корректно если переменная b, будет хранится, например, в регистре? Или надо писать код перегрузки приведения по-другому?
Если вы хотите закодировать цвет целочисленным значением, то надо использовать в операторе приведения явную формулу:
colour = (r << 24) + (g << 16) + (b << 8) + a;
или
colour = (a << 24) + (b << 16) + (g << 8) + r;
в зависимости от того, какой способ кодирования используется вашей графической библиотекой.
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Если вы хотите закодировать цвет целочисленным значением, то надо использовать в операторе приведения явную формулу:
АШ>colour = (r << 24) + (g << 16) + (b << 8) + a; АШ>или АШ>colour = (a << 24) + (b << 16) + (g << 8) + r; АШ>в зависимости от того, какой способ кодирования используется вашей графической библиотекой.
Моя задача донести компилятору, чтобы при, допустим вызове функции SomeAction, компилятор сгенерил код посылки 32 разрядного регистра/переменной в стэк, когда будет передовать параметры. По-моему в данной перегрузке он (компилятор VS2005) перед посылкой параметра в стэк сгенерит код ненужного преобразования 4 отдельных байт в 32 разрядное двойное слово, или я не прав? В графической библиотеке быстродействие критично
Здравствуйте, PavelCH, Вы писали:
PCH>Моя задача донести компилятору, чтобы при, допустим вызове функции SomeAction, компилятор сгенерил код посылки 32 разрядного регистра/переменной в стэк, когда будет передовать параметры. По-моему в данной перегрузке он (компилятор VS2005) перед посылкой параметра в стэк сгенерит код ненужного преобразования 4 отдельных байт в 32 разрядное двойное слово, или я не прав? В графической библиотеке быстродействие критично
Нормальные компиляторы они того, в курсе, что в бите 8 байт и всё такое. Так что выражение вида (r<<16) | (g<<8) | (b) может оптимизировать. А вот твои художества с преобразованием невыровненных указателей нет...
Так что начать надо с простого вопроса -- что за компилятор?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
class VRGB
{
protected:
int rgba;
public:
// Красная компонентаunsigned char getR() {return (unsigned char)( rgba ); }
// Зеленая компонентаunsigned char getG() {return (unsigned char)( rgba >> 8 ); }
// Голубая компонентаunsigned char getB() {return (unsigned char)( rgba >> 16 ); }
// Альфа-составляющаяunsigned char getA() {return (unsigned char)( rgba >> 24 ); }
public:
// Перегрузка при ведения к типу intoperator int(){return rgba;}
// Конструктор для типа int
VRGB(int Integer): rgba(Integer) {}
}
Если есть сомнения насчет скорости доступа с помощью сдвига, то можно доступаться к байтам, что чревато проблемами с порядком байт на целевой платформе.
Здравствуйте, Erop, Вы писали:
E>Нормальные компиляторы они того, в курсе, что в бите 8 байт и всё такое. Так что выражение вида (r<<16) | (g<<8) | (b) может оптимизировать. А вот твои художества с преобразованием невыровненных указателей нет...
Посмотрел я во что он превращает мои художества Тестил на следующем коде (долго возился с тем, чтобы он не сокращал все до присваивания результата SomeValue одним оператором mov [SomeValue], <результат>, наконец подобрал код ):
static int SomeValue;
static VRGB c2(10,10,10);
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
SomeValue = c2;
}
То есть делаю вывод, что компилятор не понял всю глубину моей мысли. Или я че-то не правильно объяснил ему
E>Так что начать надо с простого вопроса -- что за компилятор?
Компилятор Visual Studio 2005. Пишу под винду.
Здравствуйте, Мишень-сан, Вы писали:
МС>Не проще так?
PCH>>
PCH>>struct VRGB
PCH>>{
PCH>>public:
PCH>> union
PCH>> {
PCH>> struct
PCH>> {
PCH>> // Красная компонента
PCH>> unsigned char red;
PCH>> // Зеленая компонента
PCH>> unsigned char green;
PCH>> // Голубая компонента
PCH>> unsigned char blue;
PCH>> // Альфа-составляющая
PCH>> unsigned char alpha;
PCH>> // Цвет в виде целого
PCH>> };
PCH>> unsigned int color;
PCH>> };
PCH>>public:
PCH>> // Перегрузка при ведения к типу int
PCH>> operator int& () { return color; }
PCH>> operator const int& () const { return color; }
PCH>> // Конструктор для типа int
PCH>> VRGB(unsigned int other) { color = other; }
PCH>>};
PCH>>void SomeAction(int SomeValue)
PCH>>{
PCH>>...
PCH>>}
PCH>>int main()
PCH>>{
PCH>> int a;
PCH>> VRGB b;
PCH>> b = a;
PCH>> a = b;
PCH>> SomeAction(b);
PCH>>}
PCH>>
МС>В результате все четыре компоненты автоматом пакуются в целое.
Почти так было раньше Раньше у меня был просто union и struct без класса (то есть всегда писал i = rgb.l. Я захотел повзрослому через классы, через перегрузку. Но до такого варианта, который вы предложили, конечно не додумался.
Я так понял вопрос решен. Всем спасибо, теперь буду знать методику
В догонку вопрос к автору, а обязательно ли ставить амперсанд в конструкции:
Здравствуйте, PavelCH, Вы писали:
PCH>В догонку вопрос к автору, а обязательно ли ставить амперсанд в конструкции:
PCH>
PCH>operator int& ()
PCH>
PCH>На что влияет если без него?
Не обязательно. Просто это приводит к возврату не копии значения, а ссылки на него.
Т.е. потом можно писать
...
VRGB rgb;
(int)rgb = 12345;
...
Как результат, если некая функция принимает ссылку на целое для изменений в своих потрохах, ей можно будет внаглую передавать Ваш тип, он будет автоматом преобразован к ссылке на целое, и функция его молча поменяет.
Хотя, вот подумал...
Скорее это будет небезопасно. Лучше явно описывать свои намерения.
Если надо работать с типом как с обычным int, операторы перегрузить придётся всё равно. Иначе в каждом присваивании придётся писать явное приведение.
Если не полностью в курсе, что есть ссылки и чем они отличаются от указателей, советую почитать соотв. раздел Страуструпа "С++".
Если же коротко, ссылки в отличие от указателей:
1. Инициализируются при создании, в дальнейшем переопределению не подлежат.
2. Ведут себя как сам объект или значение, на который ссылаются.
3. Могут быть инициализированы только lvalue (грубо — переменными).
Активно применяются в перегрузке операторов; также неплохо применять, когда надо передать в функцию объект или структуру большого объёма, копировать которую нежелательно.
Здравствуйте, Erop, Вы писали:
E>Нормальные компиляторы они того, в курсе, что в бите 8 байт и всё такое. Так что выражение вида (r<<16) | (g<<8) | (b) может оптимизировать. А вот твои художества с преобразованием невыровненных указателей нет...
Это врядли. Единственное что может быть проверка указателя на 0, поскольку 0всегда 0, даже при смене офсета. Но не в этом случае и у какогото очень тупого компилятора. Можно к ссылке приводить. Ссылки void& не бывает, поэтому ссылку ни проверять ноль, ни промежуточно использовать { (Y&)(void&)X; } не нужно.
Здравствуйте, Programador, Вы писали:
E>>А вот твои художества с преобразованием невыровненных указателей нет...
P>Это врядли.
Ещё будет чтение невыровненного int...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, andrey.desman, Вы писали:
AD>Здравствуйте, Мишень-сан, Вы писали:
МС>>Не проще так? МС>>В результате все четыре компоненты автоматом пакуются в целое.
AD>Так тоже нельзя — UB, да и в добавок все равно проблемы с LE/BE. Но в большинстве случаев конечно сойдет.
Гм, а где там UB, не подскажете? Честно, не в курсе просто.
Здравствуйте, Мишень-сан, Вы писали:
МС>Здравствуйте, PavelCH, Вы писали:
PCH>>В догонку вопрос к автору, а обязательно ли ставить амперсанд в конструкции:
PCH>>
PCH>>operator int& ()
PCH>>
PCH>>На что влияет если без него?
МС>Не обязательно. Просто это приводит к возврату не копии значения, а ссылки на него. МС>Т.е. потом можно писать МС>
МС>Как результат, если некая функция принимает ссылку на целое для изменений в своих потрохах, ей можно будет внаглую передавать Ваш тип, он будет автоматом преобразован к ссылке на целое, и функция его молча поменяет.
Вменяемый компилятор не должен это компилировать, т.к. левым операндом оператора присваивания должно быть modifiable lvalue.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Вменяемый компилятор не должен это компилировать, т.к. левым операндом оператора присваивания должно быть modifiable lvalue.
Ну это был VC8.0
Хотя конструкция дурацкая, согласен.
Не знаю что меня вообще дёрнуло писать приведение к ссылке.