QT/C++类型的异常过载功能情况
Weird overload function situation with QT/C++ types
我的一位同事创建了一个重载函数,我遇到了一个奇怪的问题,但我们都是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
)。
另一方面,将字符串文字转换为QVariant
需要用户定义的转换序列,因为它涉及一个类(QVariant
)。
根据C++11 13.3.3.2/2,
当比较隐式转换序列的基本形式(如13.3.3.1中所定义)时,
- 标准转换序列(13.3.3.1.1)是比用户定义的转换更好的转换序列序列或省略号转换序列
这意味着第一个过载严格来说是更好的,因此被选择。
顺便说一句,我敢打赌你是在用Visual Studio进行构建。否则,构建
foo(QString("some_qt_string"));
甚至不会编译。这是因为QString("some_qt_string")
创建了一个临时对象,而在标准C++中,临时对象不能绑定到非常量左值引用(第二个重载使用该引用)。但是,Visual Studio允许将其作为扩展。
为什么它决定使用一个重载,它接受一个甚至不属于同一类型的可选参数,而不是使用第二个并尝试将字符串参数用作QVariant?
查看函数签名:
foo(bool arg1=false);foo(QVariant&arg1,QString&arg2=NULL,bool arg3=false);
第二个过载取一个左值。如果传递const char*
,则需要创建一个QVariant右值。
另一方面,有一个函数重载,它采用bool值,这是一个更好的匹配,并被调用。
你还说,如果你这样做:
foo(QString("some_qt_string"));
第二个被称为。但它甚至不应该编译。您正在将右值传递给采用左值的函数。我不确定你用的是哪种编译器,但那肯定是错误的。设置最大可能的警告级别,看看会发生什么。我希望你不要忽视编译器的警告;)
最简单的解决方案(也许也是最好的)是不要使函数过载。或者至少不要给出默认参数。
第二个重载引用QVariant
作为第一个参数。你没有通过QVariant
,所以这个过载永远不会被接受。事实上,当您传递QString
作为第一个参数时,第二个重载仍然不可行,您应该会得到一个编译器错误。我的猜测是,您正在使用Microsoft VC进行编译,您所观察到的是非标准行为,它允许您获取临时的l值引用。
- 如果我想在没有更新编译器的情况下使用新功能,该怎么办?
- 扩展基类并在不更改派生类的情况下使用该功能
- C++模板功能并定义特定情况
- C 交叉相关单例.在没有朋友的情况下,我如何使用彼此的功能
- 如何在不接触函数本身的情况下暂停和恢复 C++11 std::thread 的功能
- 如何在不复制的情况下将向量向量从类函数传递到功能
- 模板专业化的情况下,如果有变态模板功能
- 如何在没有对象的情况下执行插槽功能
- 如何在不引起实例化的情况下获取功能模板的签名
- 在这种情况下,(N)RVO是否适用于我的功能
- 当我想扩展当前应用程序的功能时,出现DIAMOND情况
- 默认情况下,如何制作功能指针参数NO-OP
- 在不违反干prinicple的情况下,对传递功能对象的参数类型进行模板选择
- 在不发送任何内容的情况下获取功能的返回
- LDAP函数中是否有任何功能可以在不使用ldap_search的情况下获取用户信息
- 如何在不破坏现有代码的情况下将输出参数添加到功能
- 我可以在不使用标准API功能的情况下创建过程
- 如何创建模板功能在容器和类型都是参数的情况下
- 如何在不沮丧的情况下调用派生类的成员功能
- QT/C++类型的异常过载功能情况