Qt dポインタの簡単な実現と解析
3173 ワード
/*object.h*/
#ifndef _OBJECT_H_
#define _OBJECT_H_
#define INVOKE_METHOD_PRIVATE(Class) Class##Private *d_func() {return reinterpret_cast<Class##Private*>(d_ptr);}//reinterpret_cast
#define Q_D(Class) Class##Private* d = d_func()
class ObjectData;
class ObjectPrivate;
class Object
{
INVOKE_METHOD_PRIVATE(Object)
public:
Object();// ( )Object
~Object();
Object(ObjectPrivate &dd);// Object Object
protected:
ObjectData* d_ptr;
};
#endif
/*object_p.h*/
#ifndef _OBJECT_P_H_
#define _OBJECT_P_H_
class ObjectData//
{
public:
virtual ~ObjectData() {}
};
class ObjectPrivate : public ObjectData
{
public:
ObjectPrivate();//Object
~ObjectPrivate();
};
#endif
/*object.cpp*/
#include "object.h"
#include "object_p.h"
Object::Object()
:d_ptr(new ObjectPrivate)
{
}
Object::Object(ObjectPrivate &dd)
:d_ptr(&dd)
{
}
Object::~Object()
{
}
ObjectPrivate::ObjectPrivate()
{
}
ObjectPrivate::~ObjectPrivate()
{
}
/*widget.h*/
#ifndef _WIDGET_H_
#define _WIDGET_H_
#include <iostream>
#include "object.h"
using namespace std;
class WidgetPrivate;//Widget
class Widget : public Object
{
INVOKE_METHOD_PRIVATE(Widget)
public:
Widget();
~Widget();
void setWidth(int);//set
void setHeight(int);
int getWidth();//get
int getheight();
};
#endif
/*widget_p.h*/
#ifndef _WIDGET_P_H_
#define _WIDGET_P_H_
#include "object_p.h"
class WidgetPrivate : public ObjectPrivate
{
public:
int nWidth;
int nHeight;
};
#endif
/*widget.cpp*/
#include "widget.h"
#include "widget_p.h"
Widget::Widget()
:Object(*new WidgetPrivate)
{
}
Widget::~Widget()
{
}
void Widget::setWidth(int n)
{
Q_D(Widget);// ,d
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;
}
/*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;
system("pause");
return 0;
}
1.dポインタは実は対応するクラスのデータクラスポインタで、このクラスの一般的な後ろはすべてPrivateの字です
2.INVOKE_METHOD_PRIVATE解析後にプライベートメンバー関数が得られた
3.Q_D解析の後、上記のプライベートメンバー関数を呼び出す
4.なぜreinterpret_を使うのかcast?ここでまずこのd_を肯定できるからだ.ptrの変換は親、子、孫...間で行われるのは、2つの状況を考慮するか、d_ptrはnew ObjectPrivateで、変換して自分に変えて、安全で、あるいはd_ptr=new WidgetPrivate、変換後にObjectPrivate*に移行するのも安全です.残りの状況も同じだ.
5.なぜ変換するのか、そのまま使えばいいのではないでしょうか.そのまま使うと、多態を思い出す、d_ptrは確かに自分やサブクラスで初期化されていますが、虚関数はどこにあるのか、サブクラスのメンバーにアクセスするためにn多虚関数を追加することはできません....
6.hファイルには、宣言されたクラスに対して具体的に使用されていないため、パラメータタイプとして使用したり、値を返したりすることが安全です.
7.Widget_p.hファイル内のクラスの実装はWidget.cppの中、どうして?この文章はまだqポインタを考慮していないので、その時、この1本の特徴が現れたのかもしれません.
8.結局Qtと比べることができなくて、妥当でないところ、また大目に見てください