把代码贴上先:
- /*object.h*/
- #ifndef _OBJECT_H_
- #define _OBJECT_H_
- #include <iostream>
- #define INVOKE_METHOD_PRIVATE(Class) Class##Private *d_func() {return reinterpret_cast<Class##Private*>(d_ptr);}
- #define Q_D(Class) Class##Private* d = d_func();
- #define INVOKE_METHOD_PUBLIC(Class) Class *q_func() {return static_cast<Class*>(q_ptr);}
- #define Q_Q(Class) Class* q = q_func();
- using namespace std;
- class ObjectPrivate;
- class Object;
- class ObjectData
- {
- public:
- virtual ~ObjectData() = 0;
- Object* q_ptr;//公共类的指针
- };
- class Object
- {
- INVOKE_METHOD_PRIVATE(Object)
- public:
- Object();
- ~Object();
- Object(ObjectPrivate &dd);
- protected:
- ObjectData* d_ptr;//私有类的指针
- //ObjectPrivate* d_ptr;
- public:
- int m_nDescription;
- };
- #endif
- /*object_p.h*/
- #ifndef _OBJECT_P_H_
- #define _OBJECT_P_H_
- #include "object.h"
- class ObjectPrivate : public ObjectData
- {
- INVOKE_METHOD_PUBLIC(Object)
- public:
- ObjectPrivate();
- virtual ~ObjectPrivate();
- //Object* q_ptr;
- };
- #endif
- /*object.cpp*/
- #include "object.h"
- #include "object_p.h"
- ObjectData::~ObjectData()
- {
- }
- ObjectPrivate::ObjectPrivate()
- {
- q_ptr = 0;
- };
- ObjectPrivate::~ObjectPrivate()
- {
- };
- Object::Object()
- :d_ptr(new ObjectPrivate)
- {
- d_ptr->q_ptr = this;//初始化公共类指针,如果本类被直接调用(使用)
- m_nDescription = 5000;//本类的标签
- }
- Object::Object(ObjectPrivate &dd)
- :d_ptr(&dd)
- {
- d_ptr->q_ptr = this;//初始化公共类指针,子类被调用的同时,本方法被调用
- m_nDescription = 5000;
- }
- Object::~Object()
- {
- }
- /*widget.h*/
- #ifndef _WIDGET_H_
- #define _WIDGET_H_
- #include "object.h"
- class WidgetPrivate;
- /*enumeration*/
- enum _state//模拟QWidget的状态
- {
- OPEN = 0,
- CLOSE,
- UNKNOWN,
- };
- /*Widget's state data*/
- class WidgetData
- {
- public:
- _state m_state;
- };
- class Widget : Object
- {
- INVOKE_METHOD_PRIVATE(Widget)
- public:
- Widget();
- ~Widget();
- /*functions*/
- void setWidth(int);
- void setHeight(int);
- int getWidth();
- int getheight();
- int getSUM(void);
- long getProduct(void);
- int getDecrease(void);
- void setState(_state s);
- _state getState(void);
- WidgetData* data;//本类的状态数据封装类
- void display();//用于测试在WidgetPrivate类中使用q_ptr调用
- public:
- int m_nDescription;//本类的标签
- };
- #endif
- /*widget_p.h*/
- #ifndef _WIDGET_P_H_
- #define _WIDGET_P_H_
- #include "object_p.h"
- #include "widget.h"
- class WidgetPrivate : public ObjectPrivate
- {
- INVOKE_METHOD_PUBLIC(Widget)
- public:
- WidgetPrivate();
- ~WidgetPrivate();
- /*members*/
- int nWidth;
- int nHeight;
- WidgetData data;
- /*functions*/
- void init();
- inline int getSUM_p(void)
- {
- Q_Q(Widget)
- if(q == 0)//测试q指针
- {
- cout<<"NULL"<<endl;;
- }
- std::cout<<"Description :"<<q->m_nDescription<<std::endl;
- return nWidth+nHeight;
- }
- inline long getProduct_p(void)
- {
- return (long)(nWidth*nHeight);//this will be a problem
- }
- int getDecrease_p(void);
- void setState_p(_state s);
- _state getState_p(void);
- };
- #endif
- /*widget.cpp*/
- #include "widget.h"
- #include "widget_p.h"
- Widget::Widget()
- :Object(*new WidgetPrivate)
- {
- m_nDescription = 100;
- Q_D(Widget)
- d->init();
- }
- Widget::~Widget()
- {
- data = 0;
- }
- WidgetPrivate::WidgetPrivate()
- {
- }
- WidgetPrivate::~WidgetPrivate()
- {
- }
- void WidgetPrivate::init()
- {
- Q_Q(Widget)
- q->data = &data;
- q->display();
- }
- int WidgetPrivate::getDecrease_p(void)
- {
- return nWidth - nHeight;
- }
- //WidgetPrivate自己设置状态
- void WidgetPrivate::setState_p(_state s)
- {
- data.m_state = s;
- }
- //WidgetPrivate自己取得状态
- _state WidgetPrivate::getState_p(void)
- {
- return data.m_state;
- }
- void Widget::setWidth(int n)
- {
- Q_D(Widget)
- d->nWidth = n;
- }
- void Widget::setHeight(int n)
- {
- Q_D(Widget)
- d->nHeight = n;
- }
- int Widget::getWidth()
- {
- Q_D(Widget)
- return d->nWidth;
- }
- int Widget::getheight()
- {
- Q_D(Widget)
- return d->nHeight;
- }
- int Widget::getSUM(void)
- {
- Q_D(Widget)
- return d->getSUM_p();
- }
- long Widget::getProduct(void)
- {
- Q_D(Widget)
- return d->getProduct_p();
- }
- int Widget::getDecrease(void)
- {
- Q_D(Widget)
- return d->getDecrease_p();
- }
- //Widget自己设置状态
- void Widget::setState(_state s)
- {
- data->m_state = s;
- }
- //Widget自己取得状态
- _state Widget::getState(void)
- {
- return data->m_state;
- }
- void Widget::display()
- {
- cout<<"Widget::display()"<<endl;
- }
- /*main.cpp*/
- #include "widget.h"
- int main()
- {
- Widget w;
- w.setWidth(6);
- w.setHeight(7);
- std::cout<<"width : "<<w.getWidth()<<std::endl;
- std::cout<<"height : "<<w.getheight()<<std::endl;
- cout<<"getSUM :"<<w.getSUM()<<std::endl;
- _state s = OPEN;
- w.setState(s);
- cout<<"state : "<<static_cast<int>(w.getState())<<endl;
- system("pause");
- return 0;
- }
代码比较多,不过都是在上篇文章基础上添加的,可以先看下简单的,再来看这篇文章。
主要修改之处体现在添加了宏INVOKE_METHOD_PUBLIC和Q_Q,后者调用前者提供的私有函数返回一个临时的指向公共类的指针,例如Qt的QWidget类。同时,照着Qt,添加了一个WidgetData类,它也是放一些数据的,我不太理解这个类的具体作用,暂且把它理解为盛放关于Widget状态的数据的类,它在Widget和WidgetPrivate中都有被引用,且同时指向一个对象,所以修改它的数据是同步的。
代码其实也不多,是有规律的,恐怕您看完之后会有一些疑问,在此,我把我的疑问与解答放置于此,看看您是否也是这么认为的:
- Object,ObjectPrivate,ObjectData三者到底是什么关系?
- INVOKE_METHOD_PUBLIC宏展开后的q_func()函数中为什么是static_cast而不是像d_func()中的reinterpret_cast?
- 为什么q_ptr的初始化是用Objectd的this指针?而不是某个具体的类
我的理解:
对于问题一,Object其实是它的抽象基类和它自己合二为一了,它的抽象基类对应ObjectData,自己对应ObjectPrivate。在程序中打代码注释的地方,您可以看一下,把ObjectData去掉,把q_ptr移动到ObjectPrivate中,把d_ptr类型改为ObjectPrivate*.不当能成功编译,还能正确执行。不过,如果用汉语去仔细推敲的话,数据指针d_ptr怎么能是某个具体类的类型呢,失去了泛型概念。
对于问题二,static_cast的作用之一是在父子类之间进行转换,虽然从父类型指针转换到子类型指针不安全,但Qt这样做了,我理解不能
对于问题三,我感觉这才是q_ptr难于理解的关键原因,我上网查了很多资料,无一例外,所示例子中q_ptr的初始化全都是用具体的公共类的this去赋值,这很好理解,这不就是多态的概念吗:用父类指针指向一个已经初始化好的子类指针,需要的时候static_cast转换回子类类型,我感觉不出有什么问题,非常完美。可是,Qt不是这样做的,它对于q_ptr,全都是用QObject的this指针去初始化,这不会有问题吗?您可以自己写个程序测试一下,把初始化好的父类指针static_cast到子类指针,然后再用转换后的指针调用函数。你会发现,如果是普通函数被调用,指针是什么类型,就掉那个类型自己的函数,或者继承父类的函数,如果是虚函数被调用,指针是用什么类初始化的,调用的就是那个类的函数,现在您对比一下我的程序,然后再去Qt源码中查找q->函数的字样,会发现,这些函数(猜想)全是普通函数,,,剩下的,,,你懂了。。。。
完毕,感谢观赏。