找回密码
 立即注册
搜索
查看: 1630|回复: 8

[软件] 求助: RECT 结构,赋值语法

[复制链接]
     
发表于 2024-10-18 09:02 | 显示全部楼层 |阅读模式
VS2005、2008、2013    C++语言   DirectX 9.0

---------------------------------------------------------
RECT 结构原型:
typedef struct _RECT {
    LONG  left;
    LONG  top;
    LONG  right;
    LONG  bottom;
} RECT, *PRECT;


设置RECT变量的三种方法:
1、初始化方式
RECT  r = { 0, 0, 6, 8 };


2、单个赋值
RECT  r ;
r.left = 15;
r.top = 16;
r.right = 300;
r.bottom = 400;


3、调用SetRect函数
RECT  r ;
SetRect  ( &r , 0 , 0 , 123 , 600 );
---------------------------------------------------------
  问题: r 需频繁换值,想用如下方式赋值:
RECT  r ;
r = { 0 , 0 , 6 , 8 };              // 报错
……
r = { 5 ,  6 , 400 , 600 };      // 报错


如何实现类似 r = {12, 20, 56, 108} 这种简便赋值功能?
有说用重构=运算符,有说用宏定义的。能否给出完整代码?


回复

使用道具 举报

     
 楼主| 发表于 2024-10-18 09:22 | 显示全部楼层
本帖最后由 proof1 于 2024-10-18 09:23 编辑

用这种方式行吗,重复声明:
RECT  r = { 0, 0, 6, 8 };
……
RECT  r = { 15, 16, 300, 400 };
……
RECT  r = { 12, 20, 56, 108 };
……

编译可以通过,速度是否比 SetRect() 函数慢?
回复

使用道具 举报

     
发表于 2024-10-18 12:04 来自手机 | 显示全部楼层
在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

评分

参与人数 1战斗力 +1 收起 理由
proof1 + 1

查看全部评分

回复

使用道具 举报

     
发表于 2024-10-18 13:00 | 显示全部楼层
本帖最后由 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的组合也跨不过去(用在状态机以及消息处理函数里)。



image.png


评分

参与人数 1战斗力 +1 收起 理由
proof1 + 1

查看全部评分

回复

使用道具 举报

发表于 2024-10-18 13:39 | 显示全部楼层
咋还有人回这人,他把泥潭当百度知道用呢
回复

使用道具 举报

     
发表于 2024-10-18 14:15 | 显示全部楼层
楼主可能不是人类,会用网络问人却不会用网络搜索
回复

使用道具 举报

     
发表于 2024-10-18 14:16 | 显示全部楼层
老老实实用 SetRect,增加代码 grepability

评分

参与人数 1战斗力 +1 收起 理由
proof1 + 1

查看全部评分

回复

使用道具 举报

发表于 2024-10-18 15:20 | 显示全部楼层
#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)[4]) {
        left = arr[0];
        top = arr[1];
        right = arr[2];
        bottom = arr[3];
        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战斗力 +1 收起 理由
proof1 + 1

查看全部评分

回复

使用道具 举报

     
 楼主| 发表于 2024-10-19 18:49 | 显示全部楼层
感谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|上海互联网违法和不良信息举报中心|网上有害信息举报专区|962110 反电信诈骗|举报电话 021-62035905|Stage1st ( 沪ICP备13020230号-1|沪公网安备 31010702007642号 )

GMT+8, 2024-12-23 07:05 , Processed in 0.087222 second(s), 7 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表