我正在尝试重载一些函数以处理多种数据类型。当我将变量作为参数传递时,这是微不足道的,因此:
void fnc(int32_t d){
Serial.println((String) "int32 = " + d);
}
void fnc(char* d){
Serial.println((String) "string = " + d);
}
void fnc(bool d){
if(d){ Serial.println((String) "bool = " + "true"); }
else{ Serial.println((String) "bool = " + "false"); }
}
void fnc(float d){
Serial.println((String) "float = " + d);
}
int32_t anInt = 29339222;
char* aStr = "baloney";
bool aBool = false;
float aFloat = 3.1415;
void setup() {
Serial.begin(9600);
fnc(anInt);
fnc(aStr);
fnc(aBool);
fnc(aFloat);
}
(注意,这是在 Arduino 上,因此使用 setup() 而不是 main()。)
结果如您所料:
int32 = 29339222
串 = 胡说八道
布尔 = 假
浮动 = 3.14
现在,我需要传递文字值和变量,如下所示:
fnc(8728787);
fnc("spamoney");
fnc(true);
fnc(2.718);
编译器抱怨最后一行调用 fnc(2.718):
sketch_apr1a.ino:34:12: error: call of overloaded 'fnc(double)' is ambiguous
fnc(2.718);
我想这是因为作为文字,参数没有为编译器提供类型信息。该值的实际位可以解释为任何 4 字节类型(Arduino 上的 float 是 4 字节)而 int32_t 是 4 字节类型。
所以,有几个问题:
注意:我不想使用模板函数,因为我需要用不同的算法处理不同的类型。
注意:我现在已经通过简单地创建多个函数(即 fncInt、fncStr、fncBool 等)解决了这个问题。这可行,但是......它以错误的方式摩擦我的强迫症。
注意注意:这将是图书馆的一部分。我还想避免强迫使用它的人执行 fnc((float) 2.718) ,原因与上一条注释相同。也许这很愚蠢。我不知道。
您的问题是文字
2.718
的类型是 double
,而不是 float
。 C++ 在执行重载决策时最多允许一个内置转换和一个用户定义的转换,因此需要一个转换来匹配 fnc
的任何重载,因为没有 fnc(double)
重载。有从 double
到 int32_t
、bool
和 float
的内置转换,编译器认为它们都不比其他任何一个“更好”,因为它们都是有损转换。因此这个调用是不明确的,因为它不知道你是想调用fnc(int32_t)
、fnc(bool)
还是fnc(float)
。
如果您让浮点重载接受
double
而不是浮点数,则会出现精确匹配, 被认为比需要转换的匹配“更好”,因此会选择它。
还要注意,
float
到 double
的转换也被认为比其他提到的“更好”,因为它是无损的,而其他的是有损的,所以对于调用 fnc(aFloat)
编译器也会选择 fnc(double)
而不是其他选项。
或者,您可以将
f
后缀附加到您的浮点文字,以明确使其成为 float
。例如fnc(2.718f)
是没有歧义的。
- 为什么编译器没有出现类似8728787作为参数的问题?那应该同样模棱两可,不是吗?
这个有点复杂。在 Arduino 上,
int
可以是 16 位或 32 位,具体取决于具体的电路板。
8728787
的类型将是 int
(如果 int
是 32 位)或 long int
(如果 int
是 16 位),因为 8728787
太大而无法表示16 位。int32_t
将是 int
(如果 int
是 32 位)或 long int
(如果 int
是 16 位)的别名。无论哪种情况,
8728787
的类型都将与 int32_t
完全匹配。由于它是完全匹配,所以 fnc(int32_t)
将被选中而不是其他选项。
如果您尝试将 64 位整数传递给
fnc
,您将得到与 double
到 float
情况相同的歧义。例如,由于与 double
调用相同的原因,以下内容是不明确的:
int64_t aLongInt = 123;
fnc(aLongInt);