Qt d指针简单实现及解析

[cpp]  view plain copy
  1. /*object.h*/  
  2. #ifndef _OBJECT_H_  
  3. #define _OBJECT_H_  
  4.   
  5. #define INVOKE_METHOD_PRIVATE(Class) Class##Private *d_func() {return reinterpret_cast<Class##Private*>(d_ptr);}//reinterpret_cast将转换后的类型值转换回原始类型  
  6. #define Q_D(Class) Class##Private* d = d_func()  
  7.   
  8. class ObjectData;  
  9. class ObjectPrivate;  
  10.   
  11. class Object  
  12. {  
  13.     INVOKE_METHOD_PRIVATE(Object)  
  14. public:  
  15.     Object();//这个构造函数是给直接使用(定义)Object自己具体行为用的  
  16.     ~Object();  
  17.       
  18.     Object(ObjectPrivate &dd);//这个构造函数是给Object的子类初始时顺带初始Object用的  
  19.   
  20. protected:  
  21.     ObjectData* d_ptr;  
  22. };  
  23.   
  24. #endif   
[cpp]  view plain copy
  1. /*object_p.h*/  
  2. #ifndef _OBJECT_P_H_  
  3. #define _OBJECT_P_H_  
  4.   
  5. class ObjectData//所有数据类的抽象类  
  6. {  
  7. public:  
  8.     virtual ~ObjectData() {}  
  9. };  
  10.   
  11. class ObjectPrivate : public ObjectData  
  12. {  
  13. public:  
  14.     ObjectPrivate();//Object自己的数据类  
  15.     ~ObjectPrivate();  
  16.   
  17. };  
  18.   
  19. #endif   
[cpp]  view plain copy
  1. /*object.cpp*/  
  2. #include "object.h"  
  3. #include "object_p.h"  
  4.   
  5. Object::Object()  
  6. :d_ptr(new ObjectPrivate)  
  7. {  
  8.   
  9. }  
  10.   
  11. Object::Object(ObjectPrivate &dd)  
  12. :d_ptr(&dd)  
  13. {  
  14.   
  15. }  
  16.   
  17. Object::~Object()  
  18. {  
  19.   
  20. }  
  21.   
  22. ObjectPrivate::ObjectPrivate()  
  23. {  
  24.   
  25. }  
  26.   
  27. ObjectPrivate::~ObjectPrivate()  
  28. {  
  29.   
  30. }  
[cpp]  view plain copy
  1. /*widget.h*/  
  2. #ifndef _WIDGET_H_  
  3. #define _WIDGET_H_  
  4. #include <iostream>  
  5. #include "object.h"  
  6.   
  7. using namespace std;  
  8.   
  9. class WidgetPrivate;//Widget自己的数据类  
  10.   
  11. class Widget : public Object  
  12. {  
  13.   
  14.     INVOKE_METHOD_PRIVATE(Widget)  
  15.   
  16. public:  
  17.     Widget();  
  18.     ~Widget();  
  19.   
  20.     void setWidth(int);//set方法  
  21.     void setHeight(int);  
  22.   
  23.     int getWidth();//get方法  
  24.     int getheight();  
  25.   
  26. };  
  27.   
  28. #endif  
[cpp]  view plain copy
  1. /*widget_p.h*/  
  2. #ifndef _WIDGET_P_H_  
  3. #define _WIDGET_P_H_  
  4. #include "object_p.h"  
  5.   
  6. class WidgetPrivate : public ObjectPrivate  
  7. {  
  8. public:  
  9.     int nWidth;  
  10.     int nHeight;  
  11. };  
  12.   
  13. #endif   
[cpp]  view plain copy
  1. /*widget.cpp*/  
  2. #include "widget.h"  
  3. #include "widget_p.h"  
  4.   
  5. Widget::Widget()  
  6. :Object(*new WidgetPrivate)  
  7. {  
  8.   
  9. }  
  10.   
  11. Widget::~Widget()  
  12. {  
  13.   
  14. }  
  15.   
  16. void Widget::setWidth(int n)  
  17. {  
  18.     Q_D(Widget);//获得自己的数据类指针,d指针就是个临时的变量  
  19.     d->nWidth = n;  
  20. }  
  21.   
  22. void Widget::setHeight(int n)   
  23. {  
  24.     Q_D(Widget);  
  25.     d->nHeight = n;  
  26. }  
  27.   
  28. int Widget::getWidth()  
  29. {  
  30.     Q_D(Widget);  
  31.     return d->nWidth;  
  32. }  
  33.   
  34. int Widget::getheight()  
  35. {  
  36.     Q_D(Widget);  
  37.     return d->nHeight;  
  38. }  
[cpp]  view plain copy
  1. /*main.cpp*/  
  2. #include "widget.h"  
  3.   
  4. int main()//测试  
  5. {  
  6.     Widget w;  
  7.     w.setWidth(6);  
  8.     w.setHeight(7);  
  9.     std::cout<<"width : "<<w.getWidth()<<std::endl;  
  10.     std::cout<<"height : "<<w.getheight()<<std::endl;  
  11.   
  12.     system("pause");  
  13.     return 0;  
  14. }  

1.d指针其实就是对应类的数据类指针,这个类一般后面都是Private字样

2.INVOKE_METHOD_PRIVATE解析之后就得到了一个私有的成员函数

3.Q_D解析之后就是调用上面这个私有的成员函数

4.为什么用reinterpret_cast?因为此处首先可以肯定这个d_ptr的转换是在父类,子类,孙子类...之间进行的,考虑两种情况,要么d_ptr是new ObjectPrivate,转换后转为自己,是安全的,要么d_ptr = new WidgetPrivate,转换后转为ObjectPrivate* ,也是安全的。剩下的情况也一样。

5.为什么要转换,直接用不就行了吗?直接用的话,让我想起了多态,d_ptr的确是自己或者子类初始化的,不过虚函数在哪,不可能为了访问子类的成员,我要添加n多虚函数把....

6.h文件里面用到了前向声明,因为对声明的类,并没有具体使用它,而是把它作为参数类型,或者返回值,这是安全的

7.Widget_p.h文件里的类的实现在Widget.cpp里面,为什么?这个还真不太了解,可能是为了节省文件数,或者是为了那个q指针的方便访问,因为这篇文章还没有考虑到q指针,可能那个时候,这一条的特点就体现出来了

8.毕竟不能和Qt比,欠妥之处,还望海涵

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值