求助: RECT 结构,赋值语法
VS2005、2008、2013 C++语言 DirectX 9.0---------------------------------------------------------
RECT 结构原型:
typedef struct _RECT {
LONGleft;
LONGtop;
LONGright;
LONGbottom;
} RECT, *PRECT;
设置RECT变量的三种方法:
1、初始化方式
RECTr = { 0, 0, 6, 8 };
2、单个赋值
RECTr ;
r.left = 15;
r.top = 16;
r.right = 300;
r.bottom = 400;
3、调用SetRect函数
RECTr ;
SetRect( &r , 0 , 0 , 123 , 600 );
---------------------------------------------------------
问题: r 需频繁换值,想用如下方式赋值:
RECTr ;
r = { 0 , 0 , 6 , 8 }; // 报错
……
r = { 5 ,6 , 400 , 600 }; // 报错
如何实现类似 r = {12, 20, 56, 108} 这种简便赋值功能?
有说用重构=运算符,有说用宏定义的。能否给出完整代码?
本帖最后由 proof1 于 2024-10-18 09:23 编辑
用这种方式行吗,重复声明:
RECTr = { 0, 0, 6, 8 };
……
RECTr = { 15, 16, 300, 400 };
……
RECTr = { 12, 20, 56, 108 };
……
编译可以通过,速度是否比 SetRect() 函数慢?
在C++中直接使用 {} 初始化方式进行赋值时,只能用于变量声明时。对于像 RECT 这样的结构体,在已经声明过的变量上使用 {} 赋值会导致语法错误。要实现简便的赋值方式,确实可以通过重载 = 运算符或者宏定义来实现。
解决方案 1:重载赋值运算符
通过为 RECT 结构体重载赋值运算符,我们可以实现类似 {} 语法的赋值功能。由于 RECT 是 Windows API 中的一个标准结构体,不能直接修改其定义,因此我们可以创建一个包装类来实现这一功能。
#include <windows.h>
#include <iostream>
// 包装类
class MyRect {
public:
RECT rect;
// 默认构造函数
MyRect() {
SetRect(&rect, 0, 0, 0, 0);
}
// 参数化构造函数
MyRect(LONG left, LONG top, LONG right, LONG bottom) {
SetRect(&rect, left, top, right, bottom);
}
// 重载赋值运算符
MyRect& operator=(const MyRect& other) {
rect = other.rect;
return *this;
}
// 重载赋值运算符,接受初始化列表
MyRect& operator=(std::initializer_list<LONG> list) {
if (list.size() == 4) {
auto it = list.begin();
rect.left = *it++;
rect.top = *it++;
rect.right = *it++;
rect.bottom = *it;
}
return *this;
}
};
int main() {
MyRect r;
// 通过赋值运算符来赋值
r = {0, 0, 6, 8};
std::cout << "r: " << r.rect.left << ", " << r.rect.top << ", "
<< r.rect.right << ", " << r.rect.bottom << std::endl;
r = {5, 6, 400, 600};
std::cout << "r: " << r.rect.left << ", " << r.rect.top << ", "
<< r.rect.right << ", " << r.rect.bottom << std::endl;
return 0;
}
解决方案 2:使用宏定义
宏定义也是一种简便的方法,但其灵活性和安全性不如重载运算符。使用宏定义的方法可以避免修改代码结构,适合在不希望修改现有结构体定义时使用。
#include <windows.h>
#include <iostream>
#define SET_RECT(r, l, t, ri, b) (r.left = (l), r.top = (t), r.right = (ri), r.bottom = (b))
int main() {
RECT r;
// 使用宏定义来赋值
SET_RECT(r, 0, 0, 6, 8);
std::cout << "r: " << r.left << ", " << r.top << ", "
<< r.right << ", " << r.bottom << std::endl;
SET_RECT(r, 5, 6, 400, 600);
std::cout << "r: " << r.left << ", " << r.top << ", "
<< r.right << ", " << r.bottom << std::endl;
return 0;
}
总结
重载运算符 的方式更加灵活和现代化,适用于需要更好可维护性和扩展性的代码。
宏定义 则更加直接,适合不想进行较大代码改动的场景。
你可以根据具体需求选择最适合的方案。
神奇的ai
—— 来自 鹅球 v3.2.91 本帖最后由 CyanCloverFern 于 2024-10-18 13:07 编辑
VS2005、2008、2013 C++语言 DirectX 9.0
应该是开发工具太老了,{}赋值以及更宽松的初始化规则需要到17还是20吧,一个pod类型的结构没有道理不能使用 = {a, b, c, d}的形式
而且二楼,你想钻空子,不应该用 r = Rect {a, b, c, d} 的方式来钻吗?重定义变量把作用域搞的一团糟,除了msvc,如果遇到goto+label的组合也跨不过去(用在状态机以及消息处理函数里)。
咋还有人回这人,他把泥潭当百度知道用呢 楼主可能不是人类,会用网络问人却不会用网络搜索 老老实实用 SetRect,增加代码 grepability #include <windows.h>
// 使用宏定义
#define RECT_INITIALIZER(left, top, right, bottom) { (left), (top), (right), (bottom) }
#define SET_RECT(rect, left, top, right, bottom) \
do { \
(rect).left = (left); \
(rect).top = (top); \
(rect).right = (right); \
(rect).bottom = (bottom); \
} while(0)
// 使用运算符重载
struct RECT_WRAPPER : public RECT {
RECT_WRAPPER& operator=(const RECT& other) {
left = other.left;
top = other.top;
right = other.right;
bottom = other.bottom;
return *this;
}
RECT_WRAPPER& operator=(const LONG (&arr)) {
left = arr;
top = arr;
right = arr;
bottom = arr;
return *this;
}
};
int main() {
// 使用宏定义
RECT r1 = RECT_INITIALIZER(0, 0, 6, 8);
SET_RECT(r1, 5, 6, 400, 600);
// 使用运算符重载
RECT_WRAPPER r2 = { 0, 0, 6, 8 };
r2 = { 5, 6, 400, 600 };
return 0;
}
claude给你的答案 感谢!
页:
[1]