QTBUG 20821描述这样一个问题:
#include <QtCore/QDebug> #include <QtScript/QScriptValue> int main(int argc, char *argv[]) { QScriptValue val("dbzhang800"); qDebug()<<val.toString(); return 0; }
很简单的一个程序,编译运行,得到结果:
dbzhang800
但是,如果在.pro文件内添加了 DEFINES += QT_NO_CAST_FROM_ASCII 之后,编译运行,"没有任何警告或错误",但结果却如下:
true
QScriptValue 定义有如下的各个构造函数:
QScriptValue () QScriptValue ( const QScriptValue & other ) QScriptValue ( SpecialValue value ) QScriptValue ( bool value ) QScriptValue ( int value ) QScriptValue ( uint value ) QScriptValue ( qsreal value ) QScriptValue ( const QString & value ) QScriptValue ( const QLatin1String & value ) QScriptValue ( const char * value )
而 QT_NO_CAST_FROM_ASCII 宏的作用就是屏蔽掉最后一个构造函数。
class QScriptValue { ... #ifndef QT_NO_CAST_FROM_ASCII QT_ASCII_CAST_WARN_CONSTRUCTOR QScriptValue(const char *value); #endif ...
此处出现问题的原因是,完全匹配(exact match)的这个构造函数确实被屏蔽了,可是
QScriptValue ( bool value )
却被使用了,为什么?因为指针类型到bool类型的转换属于标准转换(standard conversion,见C++标准4.12节)
该宏的作用在QString的Manual中有介绍:
Disables automatic conversions from 8-bit strings (char *) to unicode QStrings
其目的是,强制所有需要转换为Qt字符串的C中的const char*窄字符串都使用:
不然将会编译时直接报错,比如
QString val("dbzhang800"); val = "dbzhang801";
在定义该宏的情况下,直接报错。因为没有 QString(bool) 这样的东西哈。
为了确定最佳匹配,实参到形参类型的转换可划分为四级:
其中,前3个在C++标准中又通称为标准转换序列(C++标准 13.3.3.1.1)
转换(Conversion) |
类别(Category) |
级别(Rank) |
无需转换 |
Identity |
Exact Match |
左值到右值转换 |
Lvalue Transformation |
|
数组到指针转换 |
||
函数到指针转换 |
||
限定符(Qualification)转换) |
Qualification Adjustment |
|
整数提升 |
Promotion |
Promotion |
浮点数提升 |
||
整数转换 |
Conversion |
Conversion |
浮点数转换 |
||
浮点数-整数转换 |
||
指针转换 |
||
指针到成员转换 |
||
布尔转换 |
C++ Primer 中说:
内置类型的提升和转换可能会使函数匹配传声意想不到的结果,但幸运的是,设计良好的系统很少会...
显然,这儿的 bug 是api设计问题造成...
这个,我真不知道,...,在官方解决这个问题之前,不这样用就行了吧(其实,这样用的人应该也不多)。
https://bugreports.qt.nokia.com/browse/QTBUG-20821