千万不要把 bool 当成函数参数

使用bool作为函数参数会降低代码可读性。例如,InvalidateRect函数的bool参数意义不明。建议用枚举代替bool提高代码清晰度。

我们有很多 Coding Style 或 代码规范。 但这一条可能会经常被我们所遗忘,就是我们 经常会在函数的参数里使用bool参数,这会大大地降低代码的可读性。 不信?我们先来看看下面的代码。

当你读到下面的代码,你会觉得这个代码是什么意思?

widget->repaint(false);

是不要 repaint 吗?还是别的什么意思?

看了文档后,我们才知道这个参数是 immediate,也就是说,false 代表不立即重画,true 代码立即重画。

Windows API 中也有这样一个函数:InvalidateRect,当你看到下面的代码,你会觉得是什么意思?

InvalidateRect(hwnd, lpRect,  false);

我们先不说 InvalidateRect 这个函数名取得有多糟糕,我们先说一下那个 false 参数? invalidate 意为 “让XXX无效”,false 是什么意思? 双重否定? 是肯定的意思?

如果你看到这样的代码,你会相当的费解的。 于是,你要去看一下文档,或是 InvalidateRect 的函数定义, 你会看到那个参数是 BOOL bErase,意思是:“是否要重画背景”。

这样的事情有很多,再看下面的代码,想把 str 中的 ”%USER%” 替换成真实的用户名:

str.replace("%USER%", user, false);   // Qt 3

TNND,那个 false 是什么意思?不替换吗?还是别的什么意思?

看了文档才知道,false 代表: “大小写不敏感的替换”。

其实,如果你使用枚举变量/常量,而不是 bool 变量,你会让你的代码更易读,如:

widget->repaint(PAINT::immediate);
widget->repaint(PAINT::deffer);

InvalidateRect(hwnd, lpRect, !RepantBackground);

str.replace("%USER%", user, Qt::CaseInsensitive); // Qt 4

如果对这个事不以为然的话,我们再来看一些别的示例,你不妨猜猜看看下面的代码:

component.setCentered(true, false);

这什么玩意儿啊?

看了文档你才知道,这原来是 setCentered(centered, autoUpdate);

new Textbox(300, 100, false, true);

这又是什么啊?

看了文档才知道,这是创建一个文本框,第三个参数是:“是否要滚动条”,第四个是:“是否要自动换行”。TNND!

这种情况还不算最差,看看下面的双重否定。

component.setDisabled(false);
filter.setCaseInsensitive(false)

再来一个,如果你读到下面的代码,相信你会和我一样,要么石化了,要么凌乱了。

event.initKeyEvent("keypress", true, true, null, null,
					false, false, false, false, 9, 0); 

看完这篇文章,我希望你再也 不要把bool为作为函数参数了。除非两个原因:

  • 你 100% 确认不会带来阅读上的问题,比如 Java 的 setVisible (bool).
  • 你 100% 确认你想去 写出迷一样的代码

如果你想设计一个好的 API,强烈推荐你读一下 Nokia 的 Qt 的《API Design Principles》,本文就是其中的 “Boolean Trap”。

原文链接:http://coolshell.cn/articles/5444.html

转载于:https://www.cnblogs.com/lanzhi/archive/2012/11/15/6468249.html

<think>嗯,用户这次问的是C++编译错误C2064的解决方案,看来ta正在调试代码时遇到了函数调用问题。从用户引用的两个错误类型(C4996和C2664)来看,ta应该是个正在学习Windows平台C++开发的初学者,可能正在处理字符串或Unicode相关的代码。用户虽然提供了两个引用,但实际需求很明确:要解决“项不会计算为接受0个参数函数”这个报错。这个错误本质是函数签名不匹配的典型问题,需要分步骤解释清楚。让我回忆下C2064的常见场景:最常见的是把成员函数当成普通函数调用,或者回调函数签名不符。用户引用的C2664(宽窄字符转换问题)其实也暗示ta可能在处理字符串相关函数时触发错误。需要重点说明三点核心解决方法:函数签名验证、成员函数调用方式、函数指针匹配。特别要注意提醒用户检查“看似函数但不是函数”的情况——比如数组名后面误加括号这种隐蔽错误。还应该强调错误信息中的“0个参数”是突破口,要对比编译器期望的参数个数。用户可能对模板实例化错误比较困惑,这部分需要举例说明。考虑到ta是初学者,错误示例应该用简单的函数调用,比如那个add(5)的案例就很直观。最后的预防建议,IDE智能提示和类型别名是实用技巧,特别是类型别名能减少复杂函数指针的出错概率。要不要提醒用户检查拼写错误呢?虽然看起来初级,但实际开发中确实常见。还是加上吧,放在建议第四条比较合适。编译器的静态断言检测模板错误这点也值得提,毕竟现代C++项目经常用模板。</think> 以下是针对**C++编译错误C2064: "项不会计算为接受0个参数函数"**的完整解决方案指南: --- ### **错误原因** 当代码尝试调用**不符合函数签名**的实体时触发此错误,具体分为4类: 1. **非函数实体调用** ```cpp int value = 42; value(); // 错误:变量不是函数 ``` 2. **成员函数调用签名不匹配** ```cpp class MyClass { public: void func(int param) {} }; MyClass obj; obj.func(); // 错误:缺少int参数 ``` 3. **函数指针签名错误** ```cpp typedef void(*FuncPtr)(int); FuncPtr ptr = [](int x) {}; ptr(); // 错误:缺少参数 ``` 4. **带参构造函数误用** ```cpp class Widget { public: Widget(int size) {} }; Widget obj(); // 实际声明函数而非构造对象 --- ### **解决方案** #### 1. **验证函数签名** ```cpp // 原错误代码 void add(int a, int b); add(5); // C2064 // 修正:补充缺失参数 add(5, 3); // 正确 ``` #### 2. **成员函数特殊处理** ```cpp class Timer { public: void start(bool async); }; // 错误:直接调用需绑定对象 Timer t; t.start(true); // 正确方式 // 错误修正:避免裸调用 start(true); // ❌ 改为 t.start(true) ``` #### 3. **函数指针匹配** ```cpp // 定义 using Callback = void(*)(const std::string&); Callback cb = [](const std::string& s) {}; // 错误调用 cb(); // ❌ 缺少参数 // 修正 cb("Hello"); // ✅ ``` #### 4. **构造函数优化** ```cpp // 歧义代码:声明函数而非对象 Date d(); // 实际声明函数d() // 正确构造对象 Date d; // ✅ 无参构造 Date d(2024, 7); // ✅ 带参构造 ``` #### 5. **Lambda表达式特例** ```cpp auto lambda = [](int x){ return x*2; }; lambda(); // ❌ C2064 缺少参数 // 修正 lambda(5); // ✅ 返回10 ``` --- ### **调试技巧** 1. **查看错误上下文** 编译器错误提示中的行号精确指向问题调用处: > *error C2064: term does not evaluate to a function taking 0 arguments* > *at line 27: myFunction();* 2. **签名对比工具** 使用VS的**Peek Definition**(Alt+F12)核对函数声明与调用是否一致: ```cpp // 声明处 void calculate(int precision); // 调用处 calculate(); // 此处报错 ``` --- ### **预防措施** 1. **启用类型检查** 在编译选项中添加:`/W4 /analyze` 增强签名检测 2. **智能指针辅助** ```cpp std::function<void(int)> callback = [...]{}; if(callback) callback(100); // 避免空调用 ``` 3. **IDE实时校验** VS/Qt Creator等工具的**实时波浪线提示**可提前捕获签名不匹配 4. **类型别名优化** 复杂函数指针使用`using`增强可读性: ```cpp using ComplexFunc = int(*)(const std::string&, double); ``` --- > 典型修正案例:某开发者误将`std::vector::size()`当作无参函数调用,实际正确写法为`vec.size`(无括号)[^1]。若需模板深度分析,可结合`static_assert`验证可调用性: > ```cpp > template<typename F> > void call(F f) { > static_assert(std::is_invocable<F>::value, "Not callable!"); > f(); > } > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值