QT_NO_CAST_FROM_ASCII 副作用一则(QTBUG20821)

问题

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节)

QT_NO_CAST_FROM_ASCII

该宏的作用在QString的Manual中有介绍:

Disables automatic conversions from 8-bit strings (char *) to unicode QStrings

其目的是,强制所有需要转换为Qt字符串的C中的const char*窄字符串都使用:

  • QLatin1String(const char*)
  • QObject::tr(const char *)
  • QString::fromXXXX
  • QTextCodec::toUnicode ( const char *)
  • ...

不然将会编译时直接报错,比如

QString val("dbzhang800");
val = "dbzhang801";

在定义该宏的情况下,直接报错。因为没有 QString(bool) 这样的东西哈。

重载函数的最佳匹配

为了确定最佳匹配,实参到形参类型的转换可划分为四级:

  • exact match ,实参与形参类型相同
  • promotion
  • standard conversion
  • class-type conversion (通过类类型转换)

其中,前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设计问题造成...

如何解决

这个,我真不知道,...,在官方解决这个问题之前,不这样用就行了吧(其实,这样用的人应该也不多)。

参考


展开阅读全文

没有更多推荐了,返回首页