c++ 重载同时使用变量和文字的函数-不明确的调用错误

o75abkj4  于 2023-04-08  发布在  其他
关注(0)|答案(1)|浏览(136)

我试图重载一些函数来处理几种数据类型。当我将变量作为参数传递时,这是微不足道的,因此:

  1. void fnc(int32_t d){
  2. Serial.println((String) "int32 = " + d);
  3. }
  4. void fnc(char* d){
  5. Serial.println((String) "string = " + d);
  6. }
  7. void fnc(bool d){
  8. if(d){ Serial.println((String) "bool = " + "true"); }
  9. else{ Serial.println((String) "bool = " + "false"); }
  10. }
  11. void fnc(float d){
  12. Serial.println((String) "float = " + d);
  13. }
  14. int32_t anInt = 29339222;
  15. char* aStr = "baloney";
  16. bool aBool = false;
  17. float aFloat = 3.1415;
  18. void setup() {
  19. Serial.begin(9600);
  20. fnc(anInt);
  21. fnc(aStr);
  22. fnc(aBool);
  23. fnc(aFloat);
  24. }

(Note,这是在Arduino上,因此setup()而不是main()。
结果如您所料:
29339222
string = baloney
bool = false
浮点数= 3.14
现在,我需要传递文字值和变量,像这样:

  1. fnc(8728787);
  2. fnc("spamoney");
  3. fnc(true);
  4. fnc(2.718);

编译器抱怨最后一行调用fnc(2.718):

  1. sketch_apr1a.ino:34:12: error: call of overloaded 'fnc(double)' is ambiguous
  2. fnc(2.718);

我想这是因为作为一个字面量,参数没有向编译器提供类型信息。值的实际位可以被解释为任何4字节类型(在Arduino上float是4字节),int32_t是4字节类型。
所以,有几个问题:
1.为什么编译器在使用8728787作为参数时没有出现类似的问题呢?这应该也是模棱两可的,不是吗?
1.我怎样才能做到这一点呢?有没有办法把所有这些类型都作为变量和文字接受呢?
注意:我不想使用模板函数,因为我需要用不同的算法处理不同的类型。
注意:我已经解决了这个问题,现在通过简单地创建多个函数,即fncInt,fncStr,fncBool等。
注意注意注意:这将是一个库的一部分。我也想避免强迫使用它的人做fnc((float)2.718),原因和前面的注解一样。也许这很傻。我不知道。
更新:非常感谢Miles Budnik和273 K的帮助。如果我将func(float d)更改为func(double d),它确实可以编译。
但是,如果我尝试传递一个int,它又会失败。

  1. int anInt2 = 12;
  2. int32_t anInt = 29339222;
  3. float aFloat = 3.1415;
  4. void setup() {
  5. Serial.begin(9600);
  6. fnc(anInt);
  7. fnc(aFloat);
  8. fnc(8728787);
  9. fnc(2.718);
  10. fnc(anInt2);
  11. }

sketch_apr1a.ino:28:13:错误:调用重载'fnc(int&)'是模糊的fnc(anInt 2);
另外,如果我把int 32改为int 64,同样会失败,同样是在双精度字面值上。

  1. void fnc(int64_t d){
  2. //Serial.println((String) "int32 = " + d);
  3. }
  4. int64_t anInt = 29339222;
  5. float aFloat = 3.1415;
  6. void setup() {
  7. Serial.begin(9600);
  8. fnc(anInt);
  9. fnc(aFloat);
  10. fnc(8728787);
  11. fnc(2.718);
  12. fnc(anInt2);
  13. }

sketch_apr1a.ino:27:14:错误:调用重载的'fnc(long int)'是不明确的fnc(8728787);^
我很感激你的建议,我确实试着从书中理解这一点;恐怕我对整件事都很困惑。谢谢你的帮助。

flvtvl50

flvtvl501#

您的问题是文本2.718的类型为double,而不是float,并且没有fnc(double)重载。C++允许在执行重载解析时隐式添加一个内置转换和一个用户定义转换。有从doubleint32_tboolint32_tboolboolboolboolboolboolboolboolboolboolboolboolboolboolboolboolboolbool、x1n1x和float,编译器认为它们中没有一个比其他任何一个“更好”,因为它们都是有损转换。因此,调用是模糊的,因为它不知道你想调用fnc(int32_t)fnc(bool)还是fnc(float)
如果你让你的浮点重载接受一个double而不是一个float,那么就会有一个完全匹配,它被认为比需要转换的匹配“更好”,所以会被选择。
还要注意,floatdouble的转换也被认为比提到的其他转换“更好”,因为它是无损的,而其他转换是有损的,所以对于fnc(aFloat)的调用,编译器也会选择fnc(double)而不是fnc(int32_t)fnc(bool)
或者,您可以将f后缀附加到浮点字面值以显式地使其成为float。例如,fnc(2.718f)不会有二义性,因为它与fnc(float)完全匹配。
1.为什么编译器在使用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)将优先于其他选项。
如果你试图向fnc传递一个64位整数,你会得到与doublefloat的情况相同的二义性。例如,下面的代码是二义性的,原因与double调用相同:

  1. int64_t aLongInt = 123;
  2. fnc(aLongInt);
展开查看全部

相关问题