把代码贴上先:
/*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->函数的字样,会发现,这些函数(猜想)全是普通函数,,,剩下的,,,你懂了。。。。
完毕,感谢观赏。