编程拾贝(一)

关于NULL,0,nullptr

1、NULL起源于C语言,定义如下

#define NULL ((void*)0)

在C++中void*是不太受欢迎的,很容易出现问题,在赋值给其他指针类型的时候会隐士转换成该类型(也就是运行时确认),C++不允许隐式转换指针,因此定义如下:

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

这里的0,是C++中惯用的表示空指针的方法,但是还是应该在申明空指针的地方用0更好,用NULL不存在类型检查(因为他是宏)

关于nullptr,是C++11中的新关键词,用来解决0指针的二义性问题(0既是int 型又可以表示空指针)

可以参考这里的例子:http://www.cnblogs.com/porter/p/3611718.html

关于Qt

Qt是一个跨平台GUI框架。

使用的是GUI模拟的方法实现跨平台,也即利用平台提供的绘图函数自己绘制所有的控件,也是Qt运行缓慢的原因之一(更多的原因是信号槽机制导致的,稍后说)

另外两种实现跨平台GUI框架的方法:

1、API的映射,缺点当然很明显,程序非常的庞大,会有很多冗余内容,关键是每个平台提供的API不尽相同,Mac OS上独有的功能windows上没有的话就会很尴尬
2、API的模拟,其实就是封装底层的API,实现局部的统一接口之后供平台库函数的统一调用

另外,在Qt开发中应该尽量少在堆上存储,默认的application是建立在栈上的,而application控制了整个Qt的生命周期和析构顺序,简历在堆上如果出现析构顺序的错误很容易发生内存泄漏(虽然程序整体结束之后操作系统会”粗暴”地回收内存,但是那块地址上的内容并没有正确地释放),更严重的是如果出现先析构了application,但是堆上的控件没有析构会发上程序的崩溃(其实就是互相间的父子继承关系发生了逻辑问题)

Qt的信号槽

信号槽即观察者模式,定义了一个广播的signal,特定的观察者slot收到信息验证之后感兴趣,调用slot的函数。(但是利用了额外的处理来实现,不是经典观察者模式,之后深究的时候再写专门的内容)

利用观察者模式进行消息传递有点意思

关于connect函数:

QMetaObject::Connection connect(const QObject , const char ,
const QObject , const char ,
Qt::ConnectionType);
QMetaObject::Connection connect(const QObject *, const QMetaMethod &,
const QObject *, const QMetaMethod &,
Qt::ConnectionType);
QMetaObject::Connection connect(const QObject , const char ,
const char *,
Qt::ConnectionType) const;
QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
const QObject *, PointerToMemberFunction,
Qt::ConnectionType)
QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
Functor);

的五种重载,注意形参,const char*的目的是为了兼容const类型(例如字面值常量或者其他常量表达式)是很值得学习的,而另外的const类型的引用使用引用的目的是为了兼容C++中的流对象,因为流对象作形参的时候是无法产生副本的,因此必须用引用来传值。

自己平时写接口也应该考虑周全,形成这种好习惯

要具有信号槽的能力必须继承QObject, 必须写上Q_OBJECT宏(放在头文件里,不然会出问题,由moc宏会生成moc_xxx 的特殊文件)来为我们提供信号槽的机制,这个宏由moc进行特殊处理,

Qt的分模块,Qt5分的更细,由Essentials Modules和Add-on Modules两部分组成,主要有QtCore,QtGui,QtMultimedia,QtNetwork,QtOpenGL(不错),QtXml等等

Qt的“主程序”QMainWindow, 包含标题栏,菜单,工具栏,状态栏,中央Widget等

QAction用来响应用户操作

关于moc

moc(Meta Object Compiler, 元对象编译器),在C++编译器预处理之前先对Qt的源代码预处理,展开源码中的宏产生moc_xxx开头的函数,之后再由C++编译器进行编译执行

moc是对C++的一个扩展,虽然可以用内部的模板实现很多功能,但是模板是静态的而GUI是动态,利用静态机制会很麻烦,moc使用了自己的机制,Qt认为(一个信号槽大约是4个模板调用)在现代计算机的性能面前可以忽略。(但是你考虑过开发者么?项目里一个Qt的程序编译之后,我去楼下洗手间之后再上来喝了杯茶终于编译好了:))

QWidget

它是一切组件的父类,QWidget继承自QObject,继承了对象树的关系,也就是说他的坐标受父类坐标的制约,对象树的概念也有助于内存管理,其实就是这种生成关系有助于析构的顺序

养成良好的构造顺序,在生成实例的时候就指定父元素(约束产生顺序,防止局部变量析构的时候出现2次析构的问题),例如下面的例子:

{
QPushButton quit(“Quit”);
QWidget window;
quit.setParent(&window);
}

关于订阅者模式

订阅者模式首先由两种类型的对象:

1、发布者
2、观察者

发布者中应该有一个容器来存储观察者的对象,每次发生更新内容的时候调用update函数来通知每个对象,并且讲消息传递,观察者的receive函数接受消息,并且做出是否感兴趣的判断,来选择是否接受消息

你可能感兴趣的:(C++,qt,订阅者模式)