- 浏览: 395016 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (285)
- test (0)
- 分类 (1)
- java (281)
- tttttttttttt (1)
- android程序复制数据库 (1)
- Hibernate 动态 HQL (1)
- java编写扑克的洗牌程序 (1)
- NIO 之 选择就绪模式 (1)
- wpo另类问题:不可轻视的蜘蛛爬行对服务器造成的负担 (1)
- haml (1)
- cvcvcvc (1)
- 开源史上最成功的8个开源产品 (1)
- XML文件转换成Word文件或者Excel文件 (1)
- 一些利用开源浏览器核心开发专用浏览器的连接 (1)
- 毛笔效果简单思路 (1)
- 年终考评以后 (1)
- RFC821 简单邮件传输协议(SMTP)中文定义文档 (1)
- JNI中jstring类型与c语言中的字符串的转换 (1)
- 极限编程(XP)的重构与设计模式 (1)
- MapInfo2005年第三期电子新闻 (1)
- 想到目前各BLOG站点和搜索引擎的一点点缺陷 (1)
- 成功通过DB2的700和701考试 (1)
- 基于记录登陆信息的防止网页暴力破解方法 (1)
- Router路由 (1)
- 终于稍微完整的学习了一下Linux (1)
- android手机通讯录备份还原代码 (1)
- Qt之美(一):d指针/p指针详解 (1)
- DB2 静默安装 (1)
- linux开机启动脚本的顺序 (1)
- Hibernate实体对象的三种状态 (1)
- Hibernate面向对象的hql语句 (1)
- ibatIS调用存储过程 (1)
- Linux启动过程(详细说明) (1)
- C3P0配置 (1)
- memcache安装 (1)
- js event.keyCode (1)
- java获取汉子首字母 (1)
- Eclipse GC log (1)
- java轻量级httpserver (1)
最新评论
-
smilea001:
我知道了,作者采用的是gbk编码,我采用的是utf-8编码,
java获取汉子首字母 -
smilea001:
我输入的也是--
java获取汉子首字母 -
di1984HIT:
写的不错啊。
Router路由 -
kaixinyou:
...
2011.07.20——— android 获得当前view在屏幕的坐标 -
zhengjianbo:
你好,可以将你的实现代码公布下吗!万分感谢!
毛笔效果简单思路
[/b]2011.11.16
[size=18px;] 首先,看了Xizhi Zhu 的这篇Qt之美(一):D指针/私有实现,对于很多批评不美的同路人,暂且不去评论,只是想支持一下Xizhi Zhu,在引用一下Jerry Sun的话,“C++需要宏定义就像需要设计模式一样。也许你不知道,宏是图灵完全(turing complete)的,至少LISP下是这样,C/C++需要宏,几乎所有重要的C/C++库都需要和依赖宏。这些都超过咱们的想象,宏能带给我们所谓语法糖(Syntax
sugar)的方便。如果你不理解,并且不能熟练使用宏,内联函数和通用模板,那么你还和熟练的C++程序员有一定距离。”<br>
这里不去评论Jerry Sun的理解,有关宏是否图灵完全,对实际编程也没有啥意义的。至少我们看到Qt用了不少。闲话少叙,书归正文。[/size]
[size=18px;]1.二进制兼容性[/size]
[size=18px;] 这里,先简单解释一下什么破坏了代码的二进制兼容性(至于二进制兼容性是什么,相信Xizhi Zhu的文章和KDE上的这篇文章,已经说的很清楚了,有时间的话再翻译一下)。换句话说,在对程序做了什么样的改变需要我们重新编译呢?看下面的例子:[/size]
<textarea readonly name="code" class="cpp">class Widget {
...
private:
Rect m_geometry;
};
class Label :public Widget {
...
String text()const{return m_text; }
private:
String m_text;
};
</textarea>[size=18px;]在这里工程名为CuteApp,Widget类包含一个私有成员变量<span style="text-align: left;">m_geometry[/size]<span style="text-align: left;">。我们编译</span><span style="text-align: left;">Widget</span><span style="text-align: left;">类,并且将其发布为</span>WidgetLib 1.0。<span style="margin: 0px; width: auto!important; float: none!important; height: auto!important; vertical-align: baseline!important;">对于WidgetLib
1.1版本,我们希望加入对样式表的支持。在Widget类中我们相应的加入了新的数据成员。</span></span>
<textarea readonly name="code" class="cpp">class Widget {
...
private:
Rect m_geometry;
String m_stylesheet; // NEW in WidgetLib 1.1
};
class Label :public Widget {
public:
...
String text()const{return m_text; }
private:
String m_text;
} ;
</textarea>[size=18px;]经过上述改变后,我们发现工程CuteApp可以通过编译,但是当运行调用WidgetLib1.0时,程序崩溃。<br>
为什么会运行出错呢?<br>
是因为我们在加入成员变量m_stylesheet后,改变了Widget和Label类的对象布局。这是由于当编译器在编译程序时,它是用所谓的offsets来标记在类中的成员变量。我们将对象布局简化,其在内存中大致形象如下所示:[/size]
<code class="cpp plain" style="margin: 0px; width: auto!important; font-family: Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important; float: none!important; height: auto!important; vertical-align: baseline!important;"><span style="font-family: Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace;"><span style="font-family: Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace; line-height: 14px;"><span style="color: #363534;"><img alt="" src="http://hi.csdn.net/attachment/201111/16/0_1321421628H7dW.gif"></span></span></span></code>
<code class="cpp plain" style="margin: 0px; width: auto!important; font-family: Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important; float: none!important; height: auto!important; vertical-align: baseline!important;">[size=18px;]在WidegetLib
1.0中,Label类的成员变量m_text还在<offset 1>。被编译器编译后,将Label::text()方法解释为获取Label对象的<offset 1>。而在WidegetLib 1.1中,由于添加新的数据成员,导致m_text的标记位变为<offset 2>。由于工程没有重新编译,c++编译器还会将在编译和运行时的对象大小认为一致。也就是说,在编译时,编译器为Label对象按照其大小在内存上分配了空间。而在运行时,由于Widget中m_stylesheet的加入导致Label的构造函数重写了已经存在的内存空间,导致了程序崩溃。[/size]</code>
<code class="cpp plain" style="margin: 0px; width: auto!important; font-family: Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important; float: none!important; height: auto!important; vertical-align: baseline!important;">[size=18px;]
所以只要版本已发布,除非重新编译工程,否则就不能更改类的结构和大小。那么,为了能够为原有类方便的引入新的功能,这就是Qt引入D指针的目的。[/size]</code>
<code class="cpp plain" style="margin: 0px; width: auto!important; font-family: Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important; float: none!important; height: auto!important; vertical-align: baseline!important;"></code><code class="cpp plain" style="margin: 0px; width: auto!important; font-family: Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important; float: none!important; height: auto!important; vertical-align: baseline!important;">[size=18px;]2.D指针[/size]</code>
[size=18px;]<code class="cpp plain" style="margin: 0px; width: auto!important; font-family: Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important; float: none!important; height: auto!important; vertical-align: baseline!important;"></strong></code>保持一个库中的所有公有类的大小恒定的问题可以通过单独的私有指针给予解决。这个指针指向一个包含所有数据的私有数据结构体。这个结构体的大小可以随意改变而不会产生副作用,应用程序只使用相关的公有类,所使用的对象大小永远不会改变,它就是该指针的大小。这个指针就被称作D指针。[/size]
[size=18px;]</span><textarea readonly name="code" class="cpp">/* widget.h */
// 私有数据结构体声明。 其定义会在 widget.cpp 或是
// widget_p.h,总之不能在此头文件
class WidgetPrivate;
class Widget {
...
Rect geometry()const;
...
private:
// d指针永远不能在此头文件中被引用
// 由于WidgetPrivate没有在此头文件中被定义,
// 任何访问都会导致编译错误。
WidgetPrivate *d_ptr;
};
/* widget_p.h */(_p 指示private)
struct WidgetPrivate {
Rect geometry;
String stylesheet;
};
/* widget.cpp */
#include "widget_p.h"
Widget::Widget()
: d_ptr(new WidgetPrivate)// 初始化 private 数据 {
}
Rect Widget::geoemtry()const{
// 本类的d指针只能被在自己的库内被访问
return d_ptr->geometry;
}
/* label.h */
class LabelPrivate;
class Label :publicWidget {
...
String text();
private:
// 自己类对应自己的d指针
LabelPrivate *d_ptr;
};
/* label.cpp */
// 这里将私有结构体在cpp中定义
struct LabelPrivate {
String text;
};
Label::Label()
: d_ptr(new LabelPrivate) {
}
String Label::text() {
return d_ptr->text;
}
</textarea><br>
[size=18px;]有了上面的结构,CuteApp就不会与d指针直接打交道。因为d指针只能在WidgetLib中被访问,在每一次对Widget修改之后都要对其重新编译,私有的结构体可以随意更改,而不需要重新编译整个工程项目。[/size]
[size=18px;][b]3.D指针的其他好处<br>除了以上优点,d指针还有如下优势:<br>
1.隐藏实现细节——我们可以不提供widget.cpp文件而只提供WidgetLib和相应的头文件和二进制文件。<br>
2.头文件中没有任何实现细节,可以作为API使用。<br>
3.由于原本在头文件的实现部分转移到了源文件,所以编译速度有所提高。<br>
其实以上的点都很细微,自己跟过源代码的人都会了解,qt是隐藏了d指针的管理和核心源的实现。像是在_p.h中部分函数的声明,qt也宣布在以后版本中将会删除。(This file is not part of the Qt API. It exists purely as animplementation detail. This header file may change from version toversion without notice, or even be removed.)[/size]
[size=18px;]4.Q指针<br>到目前为止,我们已经熟悉了指向私有结构体的d指针。而在实际中,往往它将包含私有方法(helper函数)。例如,LabelPrivate可能会有getLinkTargetFromPoint()(helper函数)以当按下鼠标时去找到相应的链接目标。在很多场合,这些helper函数需要访问公有类,例如访问一些属于Label类或是其基类Widget的函数。<br>
比方说,一个帮助函数setTextAndUpdateWidget()可能会调用Widget::update()函数去重新绘制Widget。因此,我们同样需要WidgetPrivate存储一个指向公有类的q指针。<br>[/size]
<textarea readonly name="code" class="cpp">/* widget.h */
class WidgetPrivate;
class Widget {
...
Rect geometry()const;
...
private:
WidgetPrivate *d_ptr;
};
/* widget_p.h */
struct WidgetPrivate {
// 初始化q指针
WidgetPrivate(Widget *q) : q_ptr(q) { }
Widget *q_ptr;// q-ptr指向基类API
Rect geometry;
String stylesheet;
};
/* widget.cpp */
#include "widget_p.h"
// 初始化 private 数据,将this指针作为参数传递以初始化 q-ptr指针
Widget::Widget()
: d_ptr(new WidgetPrivate(this)) {
}
Rect Widget::geoemtry()const{
return d_ptr->geometry;
}
/* label.h */
class LabelPrivate;
class Label :publicWidget {
...
String text()const;
private:
LabelPrivate *d_ptr;};
/* label.cpp */
struct LabelPrivate {
LabelPrivate(Label *q) : q_ptr(q) { }
Label *q_ptr; //Label中的q指针
String text;
};
Label::Label()
: d_ptr(new LabelPrivate(this)) {
}
String Label::text() {
return d_ptr->text;
}</textarea><br>
[size=18px;]5.进一步优化[/size]
[size=18px;]在以上代码中,每产生一个Label对象,就会为相应的LabelPrivate和WidgetPrivate分配空间。如果我们用这种方式使用Qt的类,那么当遇到像QListWidget(此类在继承结构上有6层深度),就会为相应的Private结构体分配6次空间。<br>
在下面示例代码中,将会看到,我们用私有类结构去实例化相应构造类,并在其继承体系上全部通过d指针来初始化列表。[/size]
<textarea readonly name="code" class="cpp">/* widget.h */
class Widget {
public:
Widget();
...
protected:
// 只有子类会访问以下构造函数
Widget(WidgetPrivate &d);// 允许子类通过它们自己的私有结构体来初始化
WidgetPrivate *d_ptr;
};
/* widget_p.h */
struct WidgetPrivate {
WidgetPrivate(Widget *q) : q_ptr(q) { }
Widget *q_ptr;
Rect geometry;
String stylesheet;
};
/* widget.cpp */
Widget::Widget()
: d_ptr(new WidgetPrivate(this)) {
}
Widget::Widget(WidgetPrivate &d)
: d_ptr(&d) {
}
/* label.h */
class Label :public Widget {
public:
Label();
...
protected:
Label(LabelPrivate &d);// 允许Label的子类通过它们自己的私有结构体来初始化
// 注意Label在这已经不需要d_ptr指针,它用了其基类的d_ptr
};
/* label.cpp */
#include "widget_p.h"
class LabelPrivate :public WidgetPrivate {
public:
String text;
};
Label::Label()
: Widget(*new LabelPrivate)//用其自身的私有结构体来初始化d指针
}
Label::Label(LabelPrivate &d)
: Widget(d) {
}</textarea>[size=18px;]这时候,我觉得我体会到了不一样的感觉,有点意思了吧,说不美的,可以想个更好的解决方案么?<br>
当我们建立一个Label对象时,它就会建立相应的LabelPrivate结构体(其是WidgetPrivate的子类)。它将其d指针传递给Widget的保护构造函数。这时,建立一个Label对象仅需为其私有结构体申请一次内存。Label同样也有一个保护构造函数可以被继承Label的子类使用,以提供自己对应的私有结构体。[/size]
[size=18px;]6.将q-ptr和d-ptr转换成正确类型[/size]
[size=18px;]前面一步优化导致的副作用是q-ptr和d-ptr分别是Widget和WidgetPrivate类型。这就意味着下面的操作是不起作用的。[/size]
<textarea readonly name="code" class="cpp">void Label::setText(constString &text) {
// 不起作用的,因为d_ptr是WidgetPrivate类型的,即使其指向LabelPrivate对象
d_ptr->text = text;
}</textarea>[size=18px;]所以为了在子类能够使用d指针,我们用static_cast来做强制转换。[/size]
<textarea readonly name="code" class="cpp">void Label::setText(const String &text) {
LabelPrivate *d =static_cast<LabelPrivate *>(d_ptr);// cast to our private type
d->text = text;
}
</textarea>[size=18px;]为了不让所有地方都飘满static_cast,我们才引入宏定义。[/size]
<textarea readonly name="code" class="cpp">
// global.h (macros)
#define DPTR(Class) Class##Private *d = static_cast<Class##Private *>(d_ptr)
#define QPTR(Class) Class *q = static_cast<Class *>(q_ptr)
// label.cpp
void Label::setText(constString &text) {
DPTR(Label);
d->text = text;
}
void LabelPrivate::someHelperFunction() {
QPTR(label);
q->selectAll();// 我们现在可以通过此函数来访问所有Label类中的方法
}</textarea>[size=18px;]至于,Qt中的D指针和Q指针的具体形式以及相应的宏定义,这里就不再重复,<span>Xizhi Zhu的文章中已经有写,完整的d指针和q指针的程序实例程序如下:(结合信号和槽机制)[/size][/size]
[size=18px;]<span>[/size]</span>
[size=18px;]//d_ptr.h[/size]
<textarea readonly name="code" class="cpp">#ifndef D_PTR_H
#define D_PTR_H
#include <QObject>
template <typename T> static inline T *GetPtrHelper(T *ptr) { return ptr; }
#define DECLARE_PRIVATE(Class) \
inline Class##Private* d_func() { return reinterpret_cast<Class##Private*>(GetPtrHelper(d_ptr)); } \
inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private*>(GetPtrHelper(d_ptr)); }\
friend class Class##Private;
#define DPTR(Class) Class##Private * const d = d_func()
class MyClassPrivate;
class MyClass : public QObject {
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0);
virtual ~MyClass();
void testFunc();
protected:
MyClass(MyClassPrivate &d);
private:
MyClassPrivate * const d_ptr;
DECLARE_PRIVATE(MyClass);
MyClass(const MyClass&);
MyClass& operator= (const MyClass&);
};
#endif
</textarea>[size=18px;]//d_ptr.cpp<br>[/size]
<textarea readonly name="code" class="cpp">#include "d_ptr.h"
#include "q_ptr.h"
MyClass::MyClass(QObject *parent) : QObject(parent),
d_ptr(new MyClassPrivate(this)) {}
MyClass::~MyClass() {
DPTR(MyClass);
delete d;
}
void MyClass::testFunc() {
DPTR(MyClass);
d->fool();
}</textarea><strong>[size=18px;]//q_ptr.h[/size][/b]
<textarea readonly name="code" class="cpp">#ifndef Q_PTR_H
#define Q_PTR_H
#include <QObject>
#include "d_ptr.h"
#define DECLARE_PUBLIC(Class) \
inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
friend class Class;
#define QPTR(Class) Class * const q = q_func()
class MyClassPrivate : public QObject
{
Q_OBJECT
public:
MyClassPrivate(MyClass *q, QObject *parent = 0);
virtual ~MyClassPrivate() {}
signals:
void testSgnl();
private slots:
void testSlt();
public:
void fool();
private:
MyClass * const q_ptr;
DECLARE_PUBLIC(MyClass);
};
#endif </textarea><br>
//q_ptr.cpp
<textarea readonly name="code" class="cpp">#include <stdio.h>
#include "q_ptr.h"
MyClassPrivate::MyClassPrivate(MyClass *q, QObject *parent) : QObject(parent), q_ptr(q) {
connect(this, SIGNAL(testSgnl()), this, SLOT(testSlt()));
}
void MyClassPrivate::fool() {
emit testSgnl();
}
void MyClassPrivate::testSlt() {
printf("This is a pimpl pattern sample implemented in qt's \"d_ptr, q_ptr\" way\n");
}
</textarea><br>
//main.cpp
<textarea readonly name="code" class="cpp">#include "q_ptr.h"
int main(/*int argc, char *argv[]*/) {
MyClass * d_ptr = new MyClass;
d_ptr->testFunc();
delete d_ptr;
while(1);
return 0;
}
</textarea><br><br><br><br>
发表评论
-
java轻量级httpserver
2012-02-08 11:48 1606httpclient+httpserver demo ... -
Eclipse GC log
2012-02-04 16:59 1448为了查看Eclipse GC log,需要在eclip ... -
java获取汉子首字母
2012-02-03 09:14 1547public class StringUtil { ... -
js event.keyCode
2012-02-03 09:09 1233<span style="" ... -
memcache安装
2012-02-02 12:04 1183? <blockquote> 1. ... -
C3P0配置
2012-02-02 11:34 1013cquireIncrement[3] ... -
Linux启动过程(详细说明)
2012-02-01 09:09 1603<div class="post ... -
ibatIS调用存储过程
2012-01-31 15:38 1627<p>一、ibatIS调用存储过程(调用存 ... -
Hibernate面向对象的hql语句
2012-01-11 13:14 1022Hibernate中hql条件语句的书写方式有: ? ... -
Hibernate实体对象的三种状态
2012-01-11 12:59 1300<p style="text- ... -
linux开机启动脚本的顺序
2011-12-21 15:14 1148下开机自动启动脚本所涉及的知识和方法、如下: ... -
DB2 静默安装
2011-12-21 11:59 1083<span style="color: ... -
android手机通讯录备份还原代码
2011-12-20 11:54 2968<span style="font-f ... -
终于稍微完整的学习了一下Linux
2011-12-19 12:14 1197Linux以前也装过两次,不过几乎没去用。头几天看一些 ... -
Router路由
2011-12-19 10:54 1202Router路由:设定线的轨迹,在Connection ... -
基于记录登陆信息的防止网页暴力破解方法
2011-12-17 10:49 1453对黑客方面比较感兴趣的或者是比较熟悉的,应该知道溯雪这 ... -
成功通过DB2的700和701考试
2011-12-16 17:27 882嘿嘿,原以为比较没有信心的701考试也被俺成功的攻克了 ... -
想到目前各BLOG站点和搜索引擎的一点点缺陷
2011-12-15 15:54 899感觉无聊,就到中国博客网的首页逛了逛,想看看有没有什么 ... -
MapInfo2005年第三期电子新闻
2011-12-15 10:49 933<span lang="EN-US&q ... -
极限编程(XP)的重构与设计模式
2011-12-14 20:58 1482</span></span>& ...
相关推荐
### QT编程技术详解 #### 一、QT介绍 ##### 1.1 跨平台特性 - **概述**:Qt 是一款强大的跨平台应用程序和用户界面(UI)开发框架,能够帮助开发者实现一次开发多平台部署的目标。这意味着开发者只需要编写一次源...
【知识点详解】 1. QT试题概述: QT是一个流行的开源跨平台应用程序开发框架,由Qt Company维护,主要用于构建图形用户界面(GUI)应用。QT支持多种编程语言,包括C++,并提供了一种称为Qt Quick(QML)的声明式...
### 详解C++中的this指针 #### 一、引言 在C++编程语言中,`this`指针是一个非常重要的概念,尤其在面向对象编程中扮演着关键角色。`this`指针是一个指向当前对象的指针,它允许程序员在类的成员函数内部引用该对象...
### 详解QT内存泄露问题 在探讨QT内存管理机制及如何避免内存泄露之前,我们首先应当理解何为内存泄露。内存泄露是指程序中已分配的堆内存由于未能释放,导致一直占用这部分内存空间,最终可能导致应用程序运行缓慢...
1. **Qt模块详解**: - **Qt Widgets**:这是Qt的核心模块,提供了各种GUI控件,如按钮、文本框等,用于构建用户界面。 - **Qt Quick**(QML):这是一个声明式UI设计语言,允许开发者创建动态、现代的用户界面,...
### Qt学习路线详解 #### 一、C++基础学习阶段(6-8周) ##### 1. C++语言入门 - **程序结构**: - **第一个程序**:`#include <iostream>` 引入标准输入输出库。`using namespace std;` 使程序能够直接使用`std...
【Qt智能指针QWeakPointer详解】 在C++编程中,智能指针是管理动态分配对象生命周期的关键工具。Qt框架提供了两种智能指针类型:QSharedPointer和QWeakPointer。QSharedPointer是一个强引用智能指针,它负责跟踪所...
### QT旋钮自我实现方法详解 #### 一、引言 在GUI开发中,旋钮是一种常见的用户界面元素,常用于调节数值或控制设备。本文将详细介绍如何在QT4环境下,利用C++语言实现自定义的旋钮功能,并能够设置最高和最低值。...
### Linux 下 QT 编程键盘键值捕获详解 #### 一、背景介绍 在Linux环境下,使用QT进行GUI应用程序开发时,往往需要对用户的键盘输入做出响应。本文将详细介绍如何在QT应用程序中捕获并处理键盘键值,实现简单的键盘...
- **在QT 2.x版本中**:在类定义时,只包含一个指向私有数据成员的指针。例如,在`Person`类中,我们只定义一个指向`PersonalDataPrivate`类型的指针,而具体的成员数据则存储在一个独立的`PersonalDataPrivate`对象...
- **内存管理**:探讨Qt中的内存管理机制,如智能指针的使用。 - **信号与槽**:深入理解Qt的信号与槽机制,这是Qt中实现事件驱动编程的关键。 - **QtGui控件**:详细介绍Qt提供的各种用户界面组件,如按钮、标签等...
**Qt实现的浮动工具箱详解** Qt是一个跨平台的应用程序开发框架,广泛应用于GUI编程,由C++编写。本项目是基于Qt实现的浮动工具箱,它允许用户在屏幕上自由移动和定位工具箱,增强了用户的交互体验。在这个系统中,...
QT是Qt Company开发的一种跨平台应用程序开发框架,广泛用于创建桌面、移动和嵌入式系统的用户界面和应用程序。TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,它是...
- **Qt学习之路文章列表**:一系列关于Qt学习的经验分享。 - **Qt的graphicsView框架**:深入探讨Qt中的图形视图框架。 - **AT2440EVB_II+WINCE5.0板上跑QT程序**:介绍如何在特定硬件平台上运行Qt程序。 - **OpenGL...
【QT指南针显示详解】 QT,全称Qt,是一个跨平台的应用程序开发框架,由挪威的Trolltech公司(现为The Qt Company)开发,现在是Digia公司的子公司。它被广泛用于创建图形用户界面(GUI)应用程序,同时也支持...
Qt是一个跨平台的应用程序开发框架,主要应用于图形用户界面(GUI)的开发,但同时也支持非GUI程序。它由The Qt Company提供,并且遵循LGPL和商业许可证。Qt API(应用程序编程接口)是Qt库的核心,包含了大量的类、...
- **宏的作用**:`Q_OBJECT`宏是Qt的核心特性之一,用于声明类为QObject的子类,并允许该类使用信号与槽机制。 - **如何使用**:在类定义中包含`Q_OBJECT`宏。 **1.1.6 帮助和文档** - **官方文档**:Qt提供详尽的...
QT5.1是Qt库的一个重要版本,它包含了大量的C++类,这些类构成了一个强大的框架,用于构建图形用户界面(GUI)和其他跨平台应用程序。这张图表提供了对Qt5.1中类之间关系的直观理解,这对于深入学习和开发基于Qt的...
- **内存管理**:讨论Qt中的内存分配策略,如何有效地使用智能指针和资源管理类。 - **性能分析**:介绍如何使用Qt Creator中的性能分析工具来识别和解决性能瓶颈。 - **代码优化技巧**:提供一系列代码优化的...