本文翻译自: https://wiki.qt.io/Coding_Conventions 原作者: Qt 原文发布时间:2015年1月14日
这是我们在编写Qt代码时使用的高级编码约定的概述。有关Qt代码规范,请参见Qt代码风格一文。对于QML,请参阅QML代码规范一文。
man ascii
).\nnn
(其中nnn是要在其中输入字符串的任何字符编码的八进制表示形式)或\xnn
(其中nn是十六进制)。示例:QString s = QString::fromUtf8("13\005");
\uuml
表示ü
。#include <QtCore/qwhatever.h>
。库前缀对于Mac OS X框架是必需的,对于非qmake项目也非常方便。#include <qstring.h> /* Qt类头文件 */
#include <new> /* STL 头文件 */
#include <limits.h> /* 系统头文件 */
qplatformdefs.h
,请始终将其作为第一个头文件包含。#include <private/whatever_p.h>
int(myFloat)
代替(int)myFloat
。QString s;
return condition ? s : "nothing";
// 运行时崩溃:QString与const char *
const char *
强制转换为const int *
,它将在必须将整数对齐为两字节或四字节边界的计算机上崩溃。union AlignHelper {
char c;
int i;
};
/* 全局作用域 */
static const QString x; /* 错误: 需要运行默认构造函数来初始化x。*/
static const QString y = "Hello"; /* 错误: 必须运行接受const char *的构造函数。*/
QString z; /* 超级错误行为! */
static const int i = foo(); /* 错误: foo()调用未定义,可能根本不会被调用。*/
你应该这样做:
/* 全局对象 */
static const char x[] = "someText"; /* 正常工作: 没有构造函数必须运行,x赋值在编译期。*/
static int y = 7; /* 正常工作: y将在编译期设置。*/
static MyStruct s = {1, 2, 3}; /* 正常工作: 编译期静态初始化。*/
static QString *ptr = 0; /* 指向对象的指针是ok的, 不需要运行代码来初始化ptr。*/
使用Q_GLOBAL_STATIC
代替创建全局对象:
Q_GLOBAL_STATIC(QString, s)
void foo()
{
s()->append("moo");
}
注意:作用域中的静态对象没有问题,在第一次使用时,构造函数将会运行。自C++ 11开始,这样的代码是可重入的。
char c; /* c不可能是负的,如果它是无符号的。*/
if (c > 0) { … } /* 不恰当的: c字符一致时无符号字符, 导致条件一直成立。*/
doSomething(QRegion rgn, QPoint p)
应使用doSomething(QRegion clientRegion, QPoint gravitySource)
代替。virtual
关键词。在Qt5中,在函数声明;
或{
之前使用override
关键词修饰它们。virtual
,这会导致潜在的内存泄漏问题。A库:
class Q_EXPORT X: public QList<QVariant> {};
B库:
class Q_EXPORT Y: public QList<QVariant> {};
导致后果,QList在两个库中导出会报符号冲突的问题。
for (Container::const_iterator it = c.begin(); it != c.end(); ++it) /* 错误的 */
for (Container::const_iterator it = c.cbegin(); it != c.cend(); ++it) /* 正确 */
Q[Core]Application
是单例类。一次只能有一个实例。但是,该实例可以被销毁,并且可以创建一个新实例,这很可能在ActiveQt或浏览器插件中进行。这样的代码很容易出错:static QObject *obj = 0;
if (!obj)
obj = new QObject(QCoreApplication::instance());
需要注意的是:如果QCoreApplication应用程序被销毁,则obj将是悬空指针。对静态全局对象使用Q_GLOBAL_STATIC或对qAddPostRoutine进行清理。
event()
,即使它为空。这确保widget可以在不破坏二进制兼容性的情况下得到修复。阅读命名空间中的Qt[https://wiki.qt.io/Qt_In_Namespace],并记住除测试和Webkit之外的所有Qt都是"namespaced"代码。
成员与非成员之间的决定[https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading/4421729#4421729]
一个对两个参数都一视同仁的二元操作符不应该是成员。因为,除了上述链接提到的原因外。当运算符是成员时,参数也不相等。
QLineF的示例,可惜的是它的operator ==作为成员:
QLineF lineF;
QLine lineN;
if (lineF == lineN) /* 正确:lineN隐式转换为QLineF。
if (lineN == lineF) /* 错误:QLineF无法隐式转换为QLine,并且LHS是成员,因此不进行转换。*/
如果operator ==在类之外,则转换规则将同样适用于双方。总结:范围小的值不能在前operator==
使用。
我们的公共头文件必须在某些用户的严格设置下仍然有效。所有已安装的头文件都必须遵循以下规则:
virtual int val()
,子类B具有同名int val(int x)
的重载,则A的val函数将被隐藏。使用using关键字使其再次可见:class B: public A
{
using A::val;
int val(int x);
};
this-> x = x
。#if Foo == 0 /* 错误的 */
#if defined(Foo) && (Foo == 0) /* 正确的 */
#if Foo - 0 == 0 /* 自认为这种方法很聪明,是吗?请还是老老实实改用上面的正确方法,以提高可读。*/
注意:本节尚未被统一接受。本节将作为进一步讨论的基准。
您可以使用具有以下限制的lambda:
void Foo::something()
{
...
std::generate(begin, end, []() { return Foo::someStaticFunction(); });
...
}
你应该使用简单的传递函数指针代替:
void Foo::something()
{
...
std::generate(begin, end, &Foo::someStaticFunction);
...
}
为什么会出现这一规定(不能在lambda中使用类中的静态函数)? 因为是GCC 4.7和更早版本存在一个错误,需要捕获此错误,但如果您这样做,则Clang 5.0和更高版本将产生警告:
void Foo::something()
{
...
std::generate(begin, end, [this]() { return Foo::someStaticFunction(); });
/* 警告:不使用lambda捕获'this'[-Wunused-lambda-capture] */
...
}
根据以下规则格式化lambda:
[]() { doSomething(); }
不要这样写:
[] { doSomething(); }
[]() -> bool {
something();
return isSomethingElse();
}
不要这样写:
[]() -> bool { something();
somethingElse(); }
foo([]() {
something();
});
if (anyOf(fooList,
[](Foo foo) {
return foo.isGreat();
})) {
return;
}
不要这样写:
if (anyOf(fooList, [](Foo foo) {
return foo.isGreat();
})) {
return;
}
foo([]() { return true; });
if (foo([]() { return true; })) {
...
}
(可选)在下列情况中,可以使用auto关键字。例如:如果使用auto会使代码的可读性降低,请不要使用auto。请记住,代码的看的次数比编写的次数要多。
auto something = new MyCustomType;
auto keyEvent = static_cast<QKeyEvent *>(event);
auto myList = QStringList() << QLatin1String("FooThing") << QLatin1String("BarThing");
auto it = myList.const_iterator();