【发布时间】:2020-11-13 17:41:03
【问题描述】:
为了创建自定义异常类,我需要将QString 转换为const char*。以下是上述类的主要代码:
// File "Exception.cpp"
const auto MESSAGE_PREFIX = QStringLiteral("Exception ");
Exception::Exception(const char* file, int line, const QString& cause)
: m_Message{MESSAGE_PREFIX + file + ':' + QString::number(line) + ": " + cause}
{
}
const char* Exception::what() const noexcept
{
// QString -> const char*
const auto ba = m_Message.toLocal8Bit();
return ba.constData();
}
因此,转换发生在被覆盖的方法Exception::what 中,并且返回的 C 字符串指示引发异常的文件等。
另外,我定义了一个宏THROW_EXCEPTION_IF(),它有助于抛出异常:
// File "exception_macros.h"
#include "Exception.h"
#ifdef Q_OS_WINDOWS
#define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#else
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#endif
#define THROW_EXCEPTION_IF(condition, cause)
if (condition) {
auto str = QString{};
QTextStream stream{&str};
stream << cause;
throw Exception{__FILENAME__, __LINE__, str};
}
最后,我用下面的代码测试了上面的宏:
void TestException::testMacro()
{
try {
THROW_EXCEPTION_IF(true, "Test")
QVERIFY(false);
}
catch (const std::exception& e) {
QVERIFY(true);
QCOMPARE(QString{e.what()}, QStringLiteral("Exception TestException.cpp:36: Test"));
}
}
问题是:当我在 Linux(Qt 5.7.1、GCC 6.3)上运行此测试时,它会失败并显示以下消息:
失败!:TestException::testMacro() 比较的值不一样
实际(QString{e.what()}):“异常 TestExn\u0000\u0000T\u0000e\u0000s\u0000t\u0000E\u0000x\u0000n\u0000\u0000\u0000”
预期 (QStringLiteral("Exception TestException.cpp:36: Test")): "Exception TestException.cpp:36: Test"
在 Windows (Qt 5.15) 上使用 MSVC 2019 也是同样的问题,但它适用于 MinGW 8.1。此外,在Linux上,当我将m_Message.toLocal8bit()替换为m_Message.toLatin1()时,测试成功通过。我认为 Unicode 字符有问题,但我不明白我的代码哪里有问题。非常感谢您的帮助。
【问题讨论】:
-
为什么不直接去
my_qstring.toStdString().c_str();? -
@Aziuth 如果他这样做,指针将不再有效,只要他得到它。
-
@Erwan 请提供一些代码和您要转换的字符串。如果您要转换为 Local8Bit,则不同平台之间可能会有所不同。
标签: c++ visual-studio qt qt5