我的一位同事创建的重载函数出现了一个奇怪的问题,但我们都是 C++/QT 新手,无法弄清楚出现这种情况的原因。
情况如下:
我们有一个重载函数:
foo(bool arg1 = false);
foo(const QVariant &arg1, const QString &arg2 = NULL, bool arg3 = false);
在第一个中,我们只有一个可选的 bool 参数作为值传递; 在第二个上,我们有一个 QVariant 引用、一个可选的 qstring 引用和一个 bool。
例如,当我调用时,运行时会发生什么:
foo("some_c++_string");
它没有使用第二个并将字符串转换为 QVariant,而是使用第一个并且可能会忽略参数!奇怪的是,它甚至不提示在编译时不存在 foo(char *) 的重载! 但如果我们这样做:
foo(QString("some_qt_string"));
它按预期进入第二个过载。
所以,问题是:到底为什么它决定进行重载,它接受一个甚至不是同一类型的可选参数,而不是使用第二个参数并尝试将字符串参数用作 QVariant?
这可能与将参数作为引用传递并赋予它们默认值有关,但我尝试了几种组合,但总是出错。
谢谢你的时间
最佳答案
那是因为隐式转换的顺序。将字符串文字转换为 bool
只需要一个标准的转换序列:一个数组到指针的转换(获取 const char*
)和一个 bool 值转换(获取 bool
).
另一方面,将字符串文字转换为QVariant
需要用户定义的转换序列,因为它涉及一个类(QVariant
)。
并且根据 C++11 13.3.3.2/2,
When comparing the basic forms of implicit conversion sequences (as defined in 13.3.3.1)
- a standard conversion sequence (13.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence
这意味着第一个重载严格来说更好,因此被选中。
顺便说一句,我敢打赌您正在使用 Visual Studio 进行构建。否则,构造
foo(QString("some_qt_string"));
甚至无法编译。那是因为 QString("some_qt_string")
创建了一个临时对象,而在标准 C++ 中,临时对象不能绑定(bind)到非常量左值引用(您的第二个重载需要)。但是,Visual Studio 允许将其作为扩展。
关于c++ - QT/C++ 类型的奇怪重载函数情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25764681/