百科问答小站 logo
百科问答小站 font logo



如何才能学到Qt的精髓? 第1页

  

user avatar   yao-dong-27 网友的相关建议: 
      

被邀请了很久了,一直在思考,今天终于下决心开始写回答。

这个问题的确是够大的,Qt的代码规模在整个开源世界里也是名列前茅的,这么大的项目其中的精华是非常多的,很难说得全面,实际上我对Qt也不是完全了解,里面还有很多我不熟悉的东西。

首先,我想谈的是 signal/slot,Qt算是发明了signal/slot,这个思想也被其他一些框架语言借鉴了。

谈signal/slot之前先来谈谈C++的缺欠,这个问题也被讨论很多了,这里只谈一点,C++的设计目标是面向对象语言,它不仅提供了对象的定义和构建的方式,也定义了对象间的关系,比如 继承 派生 聚合,但是它没有提供对象间通信和共享数据的方式,这个缺点在一般程序的开发上不算个大问题,我们可以自己简单实现,但是对于GUI开发,这个缺点就被放大了很多倍。GUI上的对象实在太多,窗口是对象,布局是对象,定时器是对象,而且对象间有错综复杂的关系,通信和数据交换非常频繁,比如按钮按下要通知父窗口或容器对象,滚动条变化了要通知列表对象。这种数量庞大的对象以及复杂的通信关系,可不是自己搞个简单的实现就能解决的。

说到通信和共享,其实他们是一回事,共享很多时候就是为了通信,而C++里要通信就必然要共享。

比如,一个类实例拥有另一个的指针,就可以访问对方的数据,调用对方的方法了,这实际就是共享了一个指针,这个类指针也是另一个对象的this。访问数据和调用方法其实都是通信,把对方的数据拿过来,把自己的数据送过去,交换数据就是通信。

在C++里,由于没有GC,管理大量原生指针是极其危险的,对象的生命周期不可控,野指针的出现概率会很高,大型C++ 的GUI项目参与开发的人数众多,很难保证都不犯错。

那么用观察者模式呢?其实也一样,还是共享了IObserverXXX指针。

那么发消息行不行呢?比如 MFC那样,可以,但是本质上还是共享了窗口句柄,否则消息发给谁呢?而且还带来另外的问题,就是类型安全,消息的参数是无法类型安全的。

Qt作为大型GUI项目的Framework,它必须解决这个问题,否则这个程序是写不大的,写大了就会问题层出不穷。

来看一段代码,看看Qt 的解决方案:

       Window::Window() {     QPushButton *b = new QPushButton(this);     connect(b, SIGNAL(clicked()), SLOT(on_button_clicked())); }  Window::on_button_clicked() {     QPushButton *b = qobject_cast<QPushButton*>(sender());     b->setText("clicked!"); }      

这段代码,通过Qt的signal slot机制,把QPushButton的点击事件连接到了Window的on_button_clicked响应函数上。

Window 和 QPushButton并没有互相保存对方指针,QPushButton的指针b 只是个局部变量,用过之后很快销毁,Window和QPushButton实现了通信,数据共享,事件响应,但是却没有共享指针,而且他们不受对方的生命周期影响,无论谁先销毁,这段代码都不会出错。

这种方式还是类型安全的,当signal和slot的类型不匹配的时候 connect是会报错的。

有人会说,我们用智能指针不就好了。好啊,智能指针你不会自己写吧,那么用boost?boost里能创建窗口吗?不能吧,还是要其他GUI库的,把两个异构的Framework撮合到一起也不是轻而易举的。再说了Qt出来的时候,别说Boost,STL都还没有呢。

signal/slot为对象间通信提供了非常灵活方便的实现,如果你只关心一个signal那就可以只connect一个,可以多个slot连接同一个signal,也可以一个slot连接到多个signal,Qt会负责管理连接关系和对象生命周期,对象销毁时会自动断开连接。

Qt为了实现signal/slot也是付出代价的,在无法改变C++语法的情况下,只能通过moc预编译器来扩展关键字。这大概是独一无二的实现方式了,后来的signal/slot实现要不用C++ template,或者发明种语言直接做到语法里,比如C# delegate。

最后总结下,Qt的signal/slot是为了解决对象间通信问题,同时避免共享指针造成的内存野指针和对象生命周期问题。

下一个议题,等我想好了再说。。。。

<待续>




  

相关话题

  有哪些轻量级适合阅读的优秀 C++ 开源项目? 
  为了软件更符合开源风格,c/cpp 代码缩进应该使用4空格还是2空格? 
  如何理解 “c++缺少对象级别的消息发送机制” 这句话? 
  为什么工业软件开发一般用的都是QT? 
  如何理解编程语言中「流」(stream)的概念? 
  C++ 中 new 和定位 new 的返回值都是 void*,却为什么可以被赋值给不同类型的指针? 
  如何评价博客园关于 C++ 的这篇热门文章? 
  做32位/64位跨版本编程,有什么需要注意的么? 
  vector 使用 emplace_back 会调用复制构造函数吗? 
  C++ 允许「我们都是人,所以我可以把你私有的眼睛借来随便玩,再还给你」,这难道是一种设计上的妥协? 

前一个讨论
汽车启动之后,发动机转速表会上下抖动两下再稳定,请问是什么情况?
下一个讨论
开赛车的人会不会觉得平时开车太慢?





© 2024-11-10 - tinynew.org. All Rights Reserved.
© 2024-11-10 - tinynew.org. 保留所有权利