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と比べることができなくて、妥当でないところ、また大目に見てください