QT 单元测试

需求 最近学习了 android 上面的单元测试之后,也考虑在 Qt 上进行单元测试。 解决 主要是 Qtest, 先汇总一些资料,等有时间搞几个测试 demo,再慢慢引入. https://zhuanlan.zhihu.com/p/39376945 https://blog.csdn.net/yizhou2010/article/details/78272505 https://zhuanlan.zhihu.com/p/412497880 https://www.cnblogs.com/im18620660608/p/17157968.html https://blog.csdn.net/u011942101/article/details/124074075 https://blog.csdn.net/ipfpm/article/details/109852908 https://www.cnblogs.com/lvdongjie/p/10599650.html https://blog.csdn.net/yang1fei2/article/details/125121777 https://zhuanlan.zhihu.com/p/40901748 http://www.cleartechfei.com/2022/06/qt%e9%a1%b9%e7%9b%ae%e6%90%ad%e5%bb%ba%e5%ae%8c%e6%95%b4%e7%9a%84%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95%e6%a1%86%e6%9e%b6/ 参考

<span title='2023-06-15 14:36:00 +0800 CST'>2023-06-15</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;22 words&nbsp;·&nbsp;RamLife

c++ 函数参数中是引用时,const 位置

需求 今天编译时,报错: =error: binding reference of type ‘CalibrationVoltage::RefFloat_kParamNum’ {aka ‘float (&)[3]’} to ‘const float [3]’ discards qualifiers=, 我觉得很奇怪,我明明加了 const 了,为啥还是说没有 const 呢? using RefFloat_kParamNum = float (&) [kParamNum]; RefFloat_kChannelNum_kParamNum CalibrateParam(const RefFloat_kParamNum output); 解决 怀疑是因为 const 和 using 一起作用的结果,所以稍微修改了一下,就 ok 了。根本原因要等后续再查了。 using RefFloat_const_kParamNum = const float (&) [kParamNum]; RefFloat_kChannelNum_kParamNum CalibrateParam(RefFloat_const_kParamNum output); 参考 C++编译出现binding ‘const string {aka const std::__cxx11::basic_string<char>}’ to reference of type ‘std error: binding reference of type int& to const int discards qualifiers...

<span title='2023-06-09 10:36:00 +0800 CST'>2023-06-09</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;74 words&nbsp;·&nbsp;RamLife

QT dialog 关闭时释放资源

需求 需要在 QDialog 关闭的时候,自动释放掉资源。 解决 默认情况下, QDialog 占用的内存会在 MainWindow 关闭后释放,如果想要在 QDialog 本身关闭的时候就释放,需要通过 setAttribute 方法配置 Qt::WA_DeleteOnClose 选项. CurrentGetConfigForm * current_get_config_form = nullptr; void MainWindow::on_pushButton_current_get_config_clicked() { if (!GetConfig()) return; if (current_get_config_form == nullptr) current_get_config_form = new CurrentGetConfigForm(nullptr, port_, version_, address_); current_get_config_form->setAttribute(Qt::WA_ShowModal, true); current_get_config_form->setAttribute(Qt::WA_DeleteOnClose, true); current_get_config_form->show(); //QEventLoop loop; //loop.exec(); qDebug() << "MainWindow::on_pushButton_current_get_config_clicked() end" << Qt::endl; current_get_config_form = nullptr; } 参考 Qt Dialog 内存管理问题:Dialog关闭时会自己释放自己吗?

<span title='2023-05-25 21:18:00 +0800 CST'>2023-05-25</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;60 words&nbsp;·&nbsp;RamLife

QT widget 以阻塞的模态形式打开

需求 需要把 widget 以模态形式打开,组织用户操作前一个页面。 解决 QWidget 没有 exec 这个方法,只能转化为 QDialog 之后,再使用 exec 方法。 CurrentGetConfigForm * current_get_config_form = nullptr; void MainWindow::on_pushButton_current_get_config_clicked() { if (!GetConfig()) return; if (current_get_config_form == nullptr) current_get_config_form = new CurrentGetConfigForm(nullptr, port_, version_, address_); current_get_config_form->setAttribute(Qt::WA_ShowModal, true); current_get_config_form->setAttribute(Qt::WA_DeleteOnClose, true); current_get_config_form->show(); //QEventLoop loop; //loop.exec(); qDebug() << "MainWindow::on_pushButton_current_get_config_clicked() end" << Qt::endl; current_get_config_form = nullptr; } 参考 QWidget如何exec QT 创建新窗口并且实现页面跳转 qt 增加新窗口,并显示在最前

<span title='2023-05-25 21:18:00 +0800 CST'>2023-05-25</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;59 words&nbsp;·&nbsp;RamLife

c++ 17 inline 单例模式

需求 在写硬件驱动的时候,有些串口之类的硬件,适合独占访问,适合用单例模式去实现,那么 c++ 中如何实现单例呢? 解决 c++ 17 中拓展了 inline 变量,可以在类内部直接初始化静态变量,这样就方便实现单例模式。如果是需要在多线程情况下使用,那么还可以使用 std::once_flag, std::call_once() 之类的来确保只初始化一次,使用 once 之类的需要引入头文件 <mutex . /* * 多线程条件下只执行一次 * once_flag的生命周期。它必需要比使用它的线程的生命周期要长。所以通常定义成全局变量比較好。 */ static std::once_flag init_flag; // 单例模式 class singleton_pattern { private: inline static singleton_pattern* _instance_ptr{nullptr};// C++ 17 inline static 直接初始化 private: singleton_pattern() { cout << "constructor called" << endl; } singleton_pattern(singleton_pattern&) = delete; singleton_pattern& operator=(const singleton_pattern&) = delete; public: ~singleton_pattern() { cout << "destructor called" << endl; } static singleton_pattern* get_instance() { std::call_once(init_flag, []() { if (_instance_ptr == nullptr) _instance_ptr = new singleton_pattern; }); return _instance_ptr; } void print_addr() { cout << std::format("address: {} \n", (void*)_instance_ptr); } }; 参考 C++ 17 inline static 实现单例模式...

<span title='2023-05-19 10:30:00 +0800 CST'>2023-05-19</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;118 words&nbsp;·&nbsp;RamLife

c++ 类内初始化非常量静态成员

需求 在类内直接初始化非常量静态成员,编译时给了报错: error: ISO C++ forbids in-class initialization of non-const static member 解决 解决也非常简单,使用 C++17, 然后增加 inline 标识,就可以了。 class A { virtual void fun1(){}; int a; public: static inline int b=0; } 参考 C++:错误:ISO C++ forbids in-class initialization of non-const static member ‘A::b’

<span title='2023-05-19 10:30:00 +0800 CST'>2023-05-19</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;43 words&nbsp;·&nbsp;RamLife

成员变量是数组,通过初始化列表来初始化

需求 今天编译是报错: warning: list-initializer for non-class type must not be parenthesized, 报错的地方是对类中包含的成员变量是一个数组,然后使用了列表初始化。 解决 其实这个报错提示已经说的很清楚了,对非类使用了列表初始化并且加了括号。所以解决的方法也很简单,这种数组成员变量初始化使用列表初始化时,不要加括号就 ok 了。 class Sn74cbtlv3253 { //using FuncVoidVoid = void (*)(void); using FuncVoidBool = void (*)(bool); public: enum Index { kIndex1 = 0, kIndex2, kIndex3, kIndex4, }; public: Sn74cbtlv3253(FuncVoidBool s0, FuncVoidBool s1, FuncVoidBool oe) : s0_(s0), s1_(s1), oe_(oe) {}; void Switch(Index index); void Disconnect(); private: FuncVoidBool s0_; FuncVoidBool s1_; FuncVoidBool oe_; }; class Channel { public: enum ChannelIndex { kChannel1 = 0, kChannel2, kChannel3, kChannel4, kChannel5, kChannel6, kChannel7, kChannel8, kChannel9, kChannel10, kChannel11, kChannel12, }; public: Channel(); void Switch(ChannelIndex index); void Disconnect(); private: Sn74cbtlv3253 sn74cbtlv3253_[6][2]; }; Channel::Channel() : sn74cbtlv3253_{ {{Chip1S0PinControl, Chip1S1PinControl, Chip1En1PinControl}, {Chip1S0PinControl, Chip1S1PinControl, Chip1En2PinControl}}, {{Chip2S0PinControl, Chip2S1PinControl, Chip2En1PinControl}, {Chip2S0PinControl, Chip2S1PinControl, Chip2En2PinControl}}, {{Chip3S0PinControl, Chip3S1PinControl, Chip3En1PinControl}, {Chip3S0PinControl, Chip3S1PinControl, Chip3En2PinControl}}, {{Chip4S0PinControl, Chip4S1PinControl, Chip4En1PinControl}, {Chip4S0PinControl, Chip4S1PinControl, Chip4En2PinControl}}, {{Chip5S0PinControl, Chip5S1PinControl, Chip5En1PinControl}, {Chip5S0PinControl, Chip5S1PinControl, Chip5En2PinControl}}, {{Chip6S0PinControl, Chip6S1PinControl, Chip6En1PinControl}, {Chip6S0PinControl, Chip6S1PinControl, Chip6En2PinControl}}, } { Disconnect(); } 参考 list initializer for non class type must not be parenthesized werror...

<span title='2023-05-19 10:30:00 +0800 CST'>2023-05-19</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;155 words&nbsp;·&nbsp;RamLife

成员变量是类的对象,通过初始化列表来初始化

需求 类中包含的成员变量是另外一个类的对象,如何对这种成员变量进行初始化? 解决 这种类对象成员变量初始化可以使用初始化列表。 class Hc595 { using FuncVoidVoid = void (*)(void); using FuncVoidBool = void (*)(bool); public: Hc595(FuncVoidVoid sck, FuncVoidVoid rck, FuncVoidBool bit, FuncVoidBool oe, FuncVoidVoid bit_delay) : sck_(sck), rck_(rck), bit_(bit), oe_(oe), bit_delay_(bit_delay) {}; void ShiftByte(uint8_t b); void Store(); void Display(bool en); private: FuncVoidVoid sck_; FuncVoidVoid rck_; FuncVoidBool bit_; FuncVoidBool oe_; FuncVoidVoid bit_delay_; }; class Led { public: enum LedIndex { kLed1 = 0, kLed2, kLed3, kLed4, kLed5, kLed6, kLed7, kLed8, kLed9, kLed10, kLed11, kLed12, }; public: Led(); void Set(LedIndex index, bool g, bool r, bool b); void Refresh(); void ClearData(); private: static const uint8_t kDataLength = 12; static const uint8_t kBufLength = 5; std::array<uint8_t, kDataLength> data_ {}; std::array<uint8_t, kBufLength> buf_ {}; Hc595 hc_; }; Led::Led() : hc_({SckRiseEdge, RckRiseEdge, DataBitPinControl, nullptr, nullptr}) { //hc_ = {SckRiseEdge, RckRiseEdge, DataBitPinControl, nullptr, nullptr}; hc_....

<span title='2023-05-18 10:30:00 +0800 CST'>2023-05-18</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;138 words&nbsp;·&nbsp;RamLife

成员变量是引用,需要通过初始化列表来初始化

需求 类中包含的成员变量是引用,如何对这种引用成员变量进行初始化? 解决 这种引用成员变量初始化只能使用初始化列表。 class CommandProcess { public: CommandProcess(uint64_t& send_count); private: uint64_t& msg_send_count_; }; CommandProcess::CommandProcess(uint64_t& send_count) : msg_send_count_(send_count) { } 参考 C/C++ - 类中成员变量是引用

<span title='2023-05-10 14:51:00 +0800 CST'>2023-05-10</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;24 words&nbsp;·&nbsp;RamLife

weak_ptr 给构造函数引用参数必须是 const, 否则 error: cannot bind non-const lvalue reference of type to an rvalue of type

需求 A类掌握资源,使用 shared_ptr 来指向资源。其他 B,C,D 类使用资源,在构造函数中使用 weak_ptr 作为引用参数来接收资源指针。但是编译是会报错,报错信息: error: cannot bind non-const lvalue reference of type ‘std::weak_ptr<>&’ to an rvalue of type ‘std::weak_ptr<>’ 解决 解决办法很简单,在构造函数的参数 weak_ptr 前面加上 const. std::unique_ptr<CommandProcess> process_; std::shared_ptr<MessageQueue> send_; process_ = make_unique<CommandProcess>(send_); CommandProcess::CommandProcess(const weak_ptr<MessageQueue>& send) : send_(send) { } 参考 c++ 智能指针 传参 GotW #91 Solution: Smart Pointer Parameters C/C++面试:weak_ptr的使用场景 关于c ++:我应该通过引用传递shared_ptr吗? C++ shared_ptr 作为参数和返回值的比较 C++11:再谈shared_ptr,以及shared_ptr参数传递以及构造细节 C++非const引用问题:error: cannot bind non-const lvalue reference of type 【报错】关于{Error} cannot bind non-const lvalue reference of type ‘std::String&‘ to an rvalue……的一个解决方案...

<span title='2023-05-10 11:24:00 +0800 CST'>2023-05-10</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;81 words&nbsp;·&nbsp;RamLife