当我追踪到qglobal.h的时候,我认为我可以停下来了,因为这里出现了语句
#ifdef __cplusplus
# include <type_traits>
# include <cstddef>
# include <utility>
#endif
#ifndef __ASSEMBLER__
# include <stddef.h>
#endif
其中 <type_traits> <cstddef> <utility>是c++核心的头文件,<stddef.h>是gcc所需的头文件,看起来应该是qt自己改写了其中里面一部分,我想,这里应该是Qt设计者代码框架的初始位置。
但是往后读发现它还包含了头文件qconfig.h和qtcore-config.h,进去看了一下,里面主要是qt版本和编译相关的宏定义,真是学到了,原来大程序都是这样开始的,以宏定义开始,这下真的是Qt的源头了,两个config的头文件。
#ifdef _MSC_VER
# define QT_SUPPORTS(FEATURE) (!defined QT_NO_##FEATURE)
#else
# define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE))
#endif
这个宏定义出现了我们不长见到的##(两连#),什么意思呢,就是把##后面的内容与前面的内容连在一起,而#则表示把后面的内容转换为字符串,我百度了一段代码
#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
printf("%s\n", h(f(1,2))); // 12
printf("%s\n", g(f(1,2))); // f(1,2)
return 0;
}
很明显了哈。
接着看,竟然又包含了三个头文件
#include <QtCore/qsystemdetection.h>
#include <QtCore/qprocessordetection.h>
#include <QtCore/qcompilerdetection.h>
依次进去看了一下,首先是qsystemdetection.h里面写了一些关于系统(各类系统)的宏定义标识,然后qprocessordetection.h里面写出了关于处理器(各类处理器)的一些标识,在这里面提到了一个计算机知识,即BE(高位编址)和LE(低位编址),最后看了qcompilerdetection.h,里面出现了程序员最熟悉的各类编译器的宏定义,可怕,我一定要贴出来,因为我很多都没听说过,Qt支持的编译器应该就在这里了
The compiler, must be one of: (Q_CC_x)
SYM - Digital Mars C/C++ (used to be Symantec C++)
MSVC - Microsoft Visual C/C++, Intel C++ for Windows
BOR - Borland/Turbo C++
WAT - Watcom C++
GNU - GNU C++
COMEAU - Comeau C++
EDG - Edison Design Group C++
OC - CenterLine C++
SUN - Forte Developer, or Sun Studio C++
MIPS - MIPSpro C++
DEC - DEC C++
HPACC - HP aC++
USLC - SCO OUDK and UDK
CDS - Reliant C++
KAI - KAI C++
INTEL - Intel C++ for Linux, Intel C++ for Windows
HIGHC - MetaWare High C/C++
PGI - Portland Group C++
GHS - Green Hills Optimizing C++ Compilers
RVCT - ARM Realview Compiler Suite
CLANG - C++ front-end for the LLVM compiler
多说一点,这里还出现了一个我几乎不敢写的方式,在这三个头文件里面,竟然有如下语句:
#ifndef QGLOBAL_H
# include <QtCore/qglobal.h>
#endif
意味着相互包含,虽然有宏定义去解决这个问题,可是想想还是背脊发凉,我真的不敢这么写,这次看了可以给自己壮壮胆了。
后面包含了C++的最爱:
#include <algorithm>
后面出现了匪夷所思的宏定义,我自己认为没必要,好想找个人讨论下,接我疑惑
# define QT_FORWARD_DECLARE_CLASS(name) class name;
# define QT_FORWARD_DECLARE_STRUCT(name) struct name;
# define QT_MANGLE_NAMESPACE(name) name
下面这个宏定义真是:
# define QT_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
# define QT_USE_NAMESPACE using namespace ::QT_NAMESPACE;
# define QT_BEGIN_NAMESPACE namespace QT_NAMESPACE {
# define QT_END_NAMESPACE }
# define QT_BEGIN_INCLUDE_NAMESPACE }
# define QT_END_INCLUDE_NAMESPACE namespace QT_NAMESPACE {
#ifndef QT_BEGIN_MOC_NAMESPACE
# define QT_BEGIN_MOC_NAMESPACE QT_USE_NAMESPACE
有种感觉,这种大框架的写法都是和普通程序的写法有区别的。
下面这个好像解答了我上面的疑惑
# define QT_FORWARD_DECLARE_CLASS(name) \
QT_BEGIN_NAMESPACE class name; QT_END_NAMESPACE \
using QT_PREPEND_NAMESPACE(name);
当我们写了QT_FORWARD_DECLARE_CLASS(QWindow)时我来翻译一下:
namespace QT_NAMESPACE{class Window;} using ::QT_NAMESPACE::Window;
这真的很妙,因为一个宏定义完成了一个类在命名空间的声明,如果有大量这种声明,这种宏定义看起来会很省力气,减少代码,降低出错的概率。
很好,这里我又看了Qt对于基本数据类型的宏定义,其实,我觉得这是Qt想区别于其它编译器和编辑器的一种方式,我认为这真的没什么用
typedef signed char qint8; /* 8 bit signed */
typedef unsigned char quint8; /* 8 bit unsigned */
typedef short qint16; /* 16 bit signed */
typedef unsigned short quint16; /* 16 bit unsigned */
typedef int qint32; /* 32 bit signed */
typedef unsigned int quint32; /* 32 bit unsigned */
除了看到了关于编译lib和dll的一些控制外,看到了一个Qt关于类里面含有私有构造函数和"="重载的一些说明
/*
Some classes do not permit copies to be made of an object. These
classes contains a private copy constructor and assignment
operator to disable copying (the compiler gives an error message).
*/
#define Q_DISABLE_COPY(Class) \
Class(const Class &) Q_DECL_EQ_DELETE;\
Class &operator=(const Class &) Q_DECL_EQ_DELETE;
看到了就记录一些,这其实是C++11里面的一个内容,就是把构造函数显示的表示出来,再在后面加上“=delete”,表示不允许使用该类型的构造函数。
看了这么多,真的想说,宏定义看起来真的很累。
struct AlignOfHelper
{
char c;
T type;
AlignOfHelper();
~AlignOfHelper();
};
template <class T>
struct AlignOf_Default
{
enum { Value = sizeof(AlignOfHelper<T>) - sizeof(T) };
};
template <class T> struct AlignOf : AlignOf_Default<T> { };
template <class T> struct AlignOf<T &> : AlignOf<T> {};
template <size_t N, class T> struct AlignOf<T[N]> : AlignOf<T> {};
这真的是模板里面的内容,还涉及到模板的派生,我真的忘了这里的妙处在哪。
接下来出现了一些基础数据类型、一些实用的宏、一些实用的内联函数(基本的比较)、处理data steam的函数、QString::utf16()处理函数
贴一个这里面提到的函数
/*
This function tests a float for a null value. It doesn't
check whether the actual value is 0 or close to 0, but whether
it is binary 0, disregarding sign.
*/
Q_REQUIRED_RESULT static inline Q_DECL_UNUSED bool qIsNull(float f)
{
union U {
float f;
quint32 u;
};
U val;
val.f = f;
return (val.u & 0x7fffffff) == 0;
}
这里面提供了一些Warning disabled的方法
/*
Avoid some particularly useless warnings from some stupid compilers.
To get ALL C++ compiler warnings, define QT_CC_WARNINGS or comment out
the line "#define QT_NO_WARNINGS".
*/
#if !defined(QT_CC_WARNINGS)
# define QT_NO_WARNINGS
#endif
#if defined(QT_NO_WARNINGS)
后面包含了
qtypeinfo.h,这里面定义了QTypeInfo的类,就是数据类型信息的定义;
qsysinfo.h,这里面包含了操作系统的一些信息的定义;
qlogging.h这里包含了一些日志信息的定义;
qflags.h定义了类型安全的enum;
qatomic.h提供了原子操作一些底层的封装;所谓原子操作,就是要求某一操作不被打断
qnumeric.h提供了判断NaN和Inf的函数;
qgobalstatic.h 留点下次再写吧