慎重使用Get/Set成员函数(四)CSample可以被其他类做为返回值

本文探讨了在类设计中如何合理地使用Get/Set成员函数,特别是在处理值对象时。通过具体例子说明了当一个类包含另一个值对象时,Get/Set函数的设计原则及其重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

慎重使用Get/Set成员函数(四)CSample可以被其他类做为返回值

黄国强 2011-10-11
在上文中,我们设计了一个去掉了Get/Set函数的值对象CSample。这次他作为COther 的成员,请见下面的例子。

////////////////////////////////////////////////////////////////////////////////
// COther 包含了 CSample

class COther
{
...
public:
    CSample& Get(void)const{return m_Sample;}
    void     Set(const CSample& aSample){m_Sample = aSample;}

private:
    CSample m_Sample;
};

上面的COther我们不打算把他写成值对象,所以Set是允许的。
Get可以成立的理由有两个:
1 使用者虽然用Get获得了m_Sample的引用,但是由于CSample是值对象,他无法修改CSample内部的值。想要修改该值只有通过COther的Set函数,这样的设计,保证了以免修改了该值,COther类却没有得到通知。
2 返回的CSample类是领域类,没有暴露基本的类型。


#include "Fuction.h" #define TAEM_NUMBER 2025555625 #define TAEM_ADDRESS 0x000000 //共字节,存储位置 000000 - 000003 #define SFLASH_ID 0xC84013 #include "Fuction.h" #define TAEM_NUMBER 2025555625 #define TAEM_ADDRESS 0x000000 //共字节,存储位置 000000 - 000003 #define SFLASH_ID 0xC84013 extern uint8_t TASK; extern uint8_t rtc_year, rtc_month, rtc_day, rtc_hour, rtc_min, rtc_sec; extern int sdk_begin_flag; uint32_t GD_flash_id = 0; uint32_t read_team_number = 0; uint8_t show[] = "system idle"; uint32_t sys_ticks = 0; volatile uint32_t last_sample_time = 0; TestStruct test_struct; ConfigStruct config_struct; // 定义 gCurrentRatio float gCurrentRatio = 1.0f; // 定义 ratioTaskState uint8_t ratioTaskState = 0; // 定义 ratioOutputBuffer uint8_t ratioOutputBuffer[100] = {0}; // 采样控制变量 volatile uint8_t sampling = 0; volatile uint8_t led_state = 0; uint32_t sample_period = 5000; // 默认采样周期为 5 秒 #include <stdio.h> #include "adc.h" // 包含真实的 ADC 驱动头文件 // 定义 limitTaskState uint8_t limitTaskState = 0; // 定义 limitOutputBuffer uint8_t limitOutputBuffer[100] = {0}; /** * 从Flash读取变比 */ float readRatioFromFlash(void) { uint32_t rawData = 0; spi_flash_buffer_read((uint8_t*)&rawData, 0x00010000, sizeof(uint32_t)); float ratio; memcpy(&ratio, &rawData, sizeof(float)); return ratio; } /** * 保存变比到Flash */ int saveRatioToFlash(float ratio) { spi_flash_write_enable(); spi_flash_sector_erase(0x00010000); uint32_t rawData; memcpy(&rawData, &ratio, sizeof(float)); spi_flash_buffer_write((uint8_t*)&rawData, 0x00010000, sizeof(uint32_t)); spi_flash_wait_for_write_end(); return 0; } /** * 初始化变比参数(系统启动时调用) */ void initRatioParameter(void) { gCurrentRatio = readRatioFromFlash(); // 从Flash读取变比 if (gCurrentRatio < 0.0f || gCurrentRatio > 100.0f) { gCurrentRatio = 1.0f; // 无效值设为默认 saveRatioToFlash(gCurrentRatio); } } #define RATIO_ADDRESS 0x00010000 // 扇区100 (256KB边界) #define LIMIT_ADDRESS 0x00020000 // 扇区200 (512KB边界) #define PERIOD_ADDRESS 0x00030000 // 扇区300 (768KB边界) // 通用Flash读取函数 float readFromFlash(uint32_t addr, float default_val, float min_val, float max_val) { uint32_t rawData = 0; if(spi_flash_buffer_read((uint8_t*)&rawData, addr, sizeof(uint32_t)) != SUCCESS) { return default_val; } float value; memcpy(&value, &rawData, sizeof(float)); if(value < min_val || value > max_val) { saveToFlash(addr, default_val); // 保存默认值 return default_val; } return value; } // 优化任务状态机 - 使用静态变量保持状态 void processRatioTask(void) { static uint8_t state = 0; switch(state) { case 0: // 初始化状态 sprintf((char*)ratioOutputBuffer, "Ratio=%.1f\r\nInput(0-100):", gCurrentRatio); transmit_data(ratioOutputBuffer, strlen((char*)ratioOutputBuffer)); state = 1; clear_rx_buffer(); // 清空接收缓冲区 break; case 1: // 等待输入 if (has_valid_input()) { float newRatio = parse_float_input(); if (newRatio >= 0.0f && newRatio <= 100.0f) { if (saveRatioToFlash(newRatio) == 0) { gCurrentRatio = newRatio; sprintf((char*)ratioOutputBuffer, "Success! New ratio: %.1f", newRatio); } else { sprintf((char*)ratioOutputBuffer, "Flash write error!"); } } else { sprintf((char*)ratioOutputBuffer, "Invalid range (0-100)!"); } transmit_data(ratioOutputBuffer, strlen((char*)ratioOutputBuffer)); state = 0; // 重置状态机 TASK = 0; // 清除任务标志 } break; } } // 新增采样周期设置功能 void set_sample_period(uint32_t period_ms) { if (period_ms < 100) period_ms = 100; // 最小100ms if (period_ms > 60000) period_ms = 60000; // 最大60秒 // 保存到Flash spi_flash_write_enable(); spi_flash_sector_erase(PERIOD_ADDRESS); spi_flash_buffer_write((uint8_t*)&period_ms, PERIOD_ADDRESS, sizeof(uint32_t)); spi_flash_wait_for_write_end(); // 更新当前值 sample_period = period_ms; printf("New sample period: %lums\r\n", sample_period); } /** * 在 OLED 上显示电压值 */ void oled_show_voltage(float voltage) { char voltage_str[20]; sprintf(voltage_str, "%.2f V", voltage); oled_show_string(2, 1, (u8*)voltage_str, 16); oled_refresh(); } void log_sample(float voltage) { static uint32_t count = 0; if(count % 100 == 0) { // 每100次采样保存一次 char log_entry[50]; sprintf(log_entry, "%lu,%.2f\n", get_timestamp(), voltage); write_to_sd_card(log_entry); } count++; } /** * 真实的 ADC 采样函数 */ float adc_sample(void) { // 使用真实的 ADC 采样代码 uint16_t adcValue = adc_get_result(ADC_CHANNEL_0); // 假设使用通道 0 float voltage = (adcValue * 3.3f) / 4096.0f; // 假设 ADC 参考电压为 3.3V return voltage * gCurrentRatio; // 应用变比 } /** * 定时器回调函数,用于控制采样周期 */ void systick_callback(void) { sys_ticks++; // 确保 sys_ticks 正在递增 if (sampling) { if (sys_ticks - last_sample_time >= sample_period / 1000) { // 将毫秒转换为滴答 last_sample_time = sys_ticks; // 触发采样 float voltage = adc_sample(); printf("ADC Voltage: %.2f V\r\n", voltage); // 更新 OLED 显示 oled_show_voltage(voltage); // 检查是否超过阈值 if (voltage > config_struct.limit) { led_alarm_on(); // 点亮报警 LED printf("Voltage OverLimit! Limit: %.2f V\r\n", config_struct.limit); } else { led_alarm_off(); // 关闭报警 LED } // 切换 LED 状态(每秒闪烁一次) led_state = !led_state; if (led_state) { led_on(); // 假设 LED1 用于指示采样状态 } else { led_off(); } } } } /** * 开启 ADC 采样 */ void start_sample(void) { if (!sampling) { sampling = 1; last_sample_time = sys_ticks; // 重置采样计时器 printf("Sampling started\r\n"); // 更新 OLED 显示 oled_clear(); oled_show_string(0, 0, "sampling", 8); oled_refresh(); // LED1 按 1s 周期闪烁 led_state = 1; } } /** * 停止 ADC 采样 */ void stop_sample(void) { if (sampling) { sampling = 0; printf("Sampling stopped\r\n"); oled_show_string(1, 1, (u8*)"system idle", 16); oled_refresh(); led_off(); // 关闭指示 LED } } void sys_config(void) { // 时钟初始化 systick_config(); // 串口初始化 usart_dma_init(); /*--系统上电初始化测试--*/ printf("\n"); printf("====system init====\r\n"); delay_1ms(10); // RTC初始化 RTC_Init(); // OLED初始化 oled_init(); // Flash初始化 spi_flash_init(); // FATFS初始化 bsp_tfcard_init(); initRatioParameter(); write_uint32_to_flash(TAEM_NUMBER, TAEM_ADDRESS); delay_1ms(10); read_team_number = 0; read_team_number = read_uint32_from_flash(TAEM_ADDRESS); printf("Device_ID:2025-CIMC-%d \r\n", read_team_number); printf("====system ready====\r\n"); oled_show_string(1, 1, (u8*)"system idle", 16); oled_refresh(); // 初始化参数(带默认值) gCurrentRatio = readFromFlash(RATIO_ADDRESS, 1.0f, 0.0f, 100.0f); config_struct.limit = readFromFlash(LIMIT_ADDRESS, 30.0f, 0.0f, 500.0f); sample_period = readFromFlash(PERIOD_ADDRESS, 5000, 100, 60000); // 初始化ADC adc_init(); } /** * 从Flash读取阈值 */ float readLimitFromFlash(void) { uint32_t rawData = 0; spi_flash_buffer_read((uint8_t*)&rawData, 0x00020000, sizeof(uint32_t)); float limit; memcpy(&limit, &rawData, sizeof(float)); return limit; } /** * 保存阈值到Flash */ int saveLimitToFlash(float limit) { spi_flash_write_enable(); spi_flash_sector_erase(0x00020000); uint32_t rawData; memcpy(&rawData, &limit, sizeof(float)); spi_flash_buffer_write((uint8_t*)&rawData, 0x00020000, sizeof(uint32_t)); spi_flash_wait_for_write_end(); return 0; } /** * 处理阈值设置任务(在主循环中调用) */ void processLimitTask(void) { switch (limitTaskState) { case 0: // 状态0:输出提示并等待输入 sprintf((char*)limitOutputBuffer, "Limit=%.1f\r\nInput value(0-500):\r\n", config_struct.limit); transmit_data(limitOutputBuffer, strlen((char*)limitOutputBuffer)); limitTaskState = 1; // 切换到输入等待状态 // 清空输入缓冲区 memset(rxbuffer, 0, MAX_BUFFER_SIZE); g_rx_length = 0; break; case 1: // 状态1:检测是否有新输入 if (g_transfer_complete == SET && g_rx_length > 0) { g_transfer_complete = RESET; float newLimit; // 解析输入(添加超时保护) if (sscanf((char*)rxbuffer, "%f", &newLimit) == 1) { // 验证输入有效性 if (newLimit >= 0.0f && newLimit <= 500.0f) { // 有效输入 config_struct.limit = newLimit; if (saveLimitToFlash(newLimit) == 0) { sprintf((char*)limitOutputBuffer, "limit modified success\r\nLimit = %.1f\r\n", newLimit); } else { sprintf((char*)limitOutputBuffer, "flash write error\r\nLimit=%.1f\r\n", config_struct.limit); } } else { // 无效输入(范围错误) sprintf((char*)limitOutputBuffer, "limit invalid (0-500 expected)\r\nLimit=%.1f\r\n", config_struct.limit); } } else { // 无效输入(非数字) sprintf((char*)limitOutputBuffer, "limit invalid (numeric value expected)\r\nLimit=%.1f\r\n", config_struct.limit); } // 输出结果并重置状态 transmit_data(limitOutputBuffer, strlen((char*)limitOutputBuffer)); limitTaskState = 2; // 切换到完成状态 } break; case 2: // 状态2:等待任务标志清除 if (TASK != 9) { limitTaskState = 0; // 重置状态 } break; default: limitTaskState = 0; break; } } /** * 初始化阈值参数(系统启动时调用) */ void initLimitParameter(void) { config_struct.limit = readLimitFromFlash(); // 从Flash读取阈值 if (config_struct.limit < 0.0f || config_struct.limit > 500.0f) { config_struct.limit = 30.0f; // 无效值设为默认 saveLimitToFlash(config_struct.limit); } } void sys_sdk(void) { switch (TASK) { case 1: if (sdk_begin_flag == 1) { // 设置RTC时间 rtc_setup(rtc_year, rtc_month, rtc_day, rtc_hour, rtc_min, rtc_sec); sdk_begin_flag = 0; } break; case 3: if (sdk_begin_flag == 1) { // Flash自检 GD_flash_id = spi_flash_read_id(); if (GD_flash_id == SFLASH_ID) { printf("flash.........ok\r\n"); test_struct.flash_status = 1; } else { printf("flash.........fail\r\n"); test_struct.flash_status = 0; } // TF自检 if (bsp_tfcard_init() == TF_OK) { printf("TF card.........ok\r\n"); test_struct.tf_card_status = 1; } else { printf("TF card.........fail\r\n"); test_struct.tf_card_status = 0; } // 输出 if (test_struct.flash_status == 1) { printf("flash ID: 0x%02X\r\n", GD_flash_id); } else { printf("can not find flash\r\n"); } if (test_struct.tf_card_status == 1) { test_struct.tf_memory = sd_card_capacity_get(); printf("TF card memory %" PRIu32 "KB\r\n", test_struct.tf_memory); } else { printf("can not find TFcard\r\n"); } rtc_show_time(); printf("====system selftest====\r\n"); sdk_begin_flag = 0; } break; case 4:// ratio { processRatioTask(); } break; case 5:// start { start_sample(); } break; case 6:// stop { stop_sample(); } break; case 7:// config save { // 保存配置逻辑可以在这里实现 printf("Config saved\r\n"); } break; case 8:// config read { // 读取配置逻辑可以在这里实现 printf("Config read\r\n"); } break; case 9:// limit { processLimitTask(); } break; default: break; } } void sys_usr(void) { while (1) { sys_sdk(); } }出现了Build started: Project: Project *** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin' Build target 'CIMC_GD32_fatfs_driver' compiling Fuction.c... ..\sysFunction\Fuction.c(87): error: #41: expression must have arithmetic or pointer type if(spi_flash_buffer_read((uint8_t*)&rawData, addr, sizeof(uint32_t)) != SUCCESS) { ..\sysFunction\Fuction.c(95): warning: #223-D: function "saveToFlash" declared implicitly saveToFlash(addr, default_val); // 保存默认值 ..\sysFunction\Fuction.c(109): warning: #223-D: function "clear_rx_buffer" declared implicitly clear_rx_buffer(); // 清空接收缓冲区 ..\sysFunction\Fuction.c(113): warning: #223-D: function "has_valid_input" declared implicitly if (has_valid_input()) { ..\sysFunction\Fuction.c(114): warning: #223-D: function "parse_float_input" declared implicitly float newRatio = parse_float_input(); ..\sysFunction\Fuction.c(164): warning: #223-D: function "get_timestamp" declared implicitly sprintf(log_entry, "%lu,%.2f\n", get_timestamp(), voltage); ..\sysFunction\Fuction.c(165): warning: #223-D: function "write_to_sd_card" declared implicitly write_to_sd_card(log_entry); ..\sysFunction\Fuction.c(198): warning: #223-D: function "led_alarm_on" declared implicitly led_alarm_on(); // 点亮报警 LED ..\sysFunction\Fuction.c(201): warning: #223-D: function "led_alarm_off" declared implicitly led_alarm_off(); // 关闭报警 LED ..\sysFunction\Fuction.c(207): warning: #223-D: function "led_on" declared implicitly led_on(); // 假设 LED1 用于指示采样状态 ..\sysFunction\Fuction.c(209): warning: #223-D: function "led_off" declared implicitly led_off(); ..\sysFunction\Fuction.c(243): warning: #223-D: function "led_off" declared implicitly led_off(); // 关闭指示 LED ..\sysFunction\Fuction.c(478): warning: #1-D: last line of file ends without a newline } ..\sysFunction\Fuction.c: 12 warnings, 1 error ".\Objects\Project.axf" - 1 Error(s), 12 Warning(s). Target not created.cuow
最新发布
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

acloud_csu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值