为什么C++函数调用会出现歧义?

15
class myClass {
   int arr[100];
public:
    void *get(long i, void* const to) const;
    void *get(long i, bool nog);
    void *tstfn(void* const to) { return get(0L,to); }
};

gcc -Wall 说:

dt.cpp: In member function ‘void* myClass::tstfn(void*)’:
dt.cpp:6:49: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
dt.cpp:4:9: note: candidate 1: void* myClass::get(long int, void*) const
dt.cpp:5:9: note: candidate 2: void* myClass::get(long int, bool)

1
你作为第二个参数提供了什么类型的参数?我主要出于好奇在问;我可能不太能提供帮助。 - Tommy
感谢大家! 返回 ((const myClass*const)this)->get(0L,to); 已经成功。 - Владимир Ткачёв
3个回答

26

这两个函数调用都需要进行类型转换:

  • 调用 void* 函数需要向 this 添加 const 限定符。
  • 调用 bool 函数需要将 tovoid* 转换为 bool

因此,根据重载决议规则,两者都不是比另一个更好的匹配项,因此这次调用被认为是模棱两可的。

也许你可以给第二个函数加上 const;也许你可以从第一个函数中删除它(尽管我不太喜欢这样做);也许你可以对 thisto 进行显式类型转换,以强制使用你想要的重载。


1
另外一个选项就是添加一个非const重载函数来调用const函数,可能是在类内定义的内联函数。 - Deduplicator
1
谢谢,但我对C ++还比较新,不明白为什么不能从非const方法调用const方法?这是一个例子,tstfn应该是NOT const,而get(long,void *)- const。 那么怎么才能让“this”成为const呢? - Владимир Ткачёв
1
@ВладимирТкачёв 你可以调用它,问题在于get()有两个同样好的选择 - 你想调用哪一个?如果你有其中一个,调用就没问题了。将this设为const只需使用const_cast<const myClass*>(this) - Barry
1
@ВладимирТкачёв:你可以调用const方法;但是在这里,由于存在两个可能的函数调用,每个调用都需要类型转换来匹配参数,因此会导致歧义。你可以使用static_cast<myClass const *>(this)将其转换为const - Mike Seymour
尽管我理解解决方案以及其背后一种(非常正式的)逻辑,但它不是奇怪的行为吗?'this'是一个方法的参数,但不仅仅是如此。不是吗? - Владимир Ткачёв
@ВладимирТкачёв:对于重载分辨率,this被视为函数参数。因此,在选择“最佳”重载时,this上的类型转换(即添加const/volatile限定符)与其他参数上的类型转换一起包括在选择标准中,在这种情况下存在歧义,因为两个函数调用都需要类型转换。无论一个人是否认为这是“奇怪”的问题,都是一种观点;至少在这里规则是一致的,尽管相当复杂。 - Mike Seymour

13

由于void *get(long i, void* const to)const的。

这意味着从非const函数tstfn调用它将需要将this的限定符从myClass*转换为const myClass*,因此调用这两个函数都需要对参数进行转换(this与其他参数一样处理),因此调用是有歧义的。


6

因为您的testfn是一个非const函数,它将调用get的非const版本。非const函数get需要bool而不是const void*。如果只有一个get函数存在(可能将void*作为第二个参数,无论其是否是const),则将被无歧义地调用。


@Slava 实际上是加2。 - Chantola
@Ajay,已经有2个正确的答案了,你的是错误的。 - Slava
我只是让它更清晰了,但我仍然认为原来的并不是错误的。 - Ajay
只有一个 get() 将解决明显的歧义问题。但是你的解释仍然不正确。问题不在于有两个函数,而在于两者都需要进行类型转换。 - Slava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接