Qt dポインタの簡単な実現と解析--威力強化版
dポインタを勉強して、どうしてqポインタを研究しないことができますか.正直に言って、qポインタを見てから、その理解はqポインタよりも難しいことに気づきます.
コードを貼り付けます.
コードは多いですが、前の文章に加えたものなので、まず簡単なものを見てから、この文章を見てみましょう.
主な修正点はマクロINVOKEが追加されたことです.METHOD_PUBLICとQ_Q.後者は、前者が提供するプライベート関数を呼び出して、QtのQWidgetクラスのような一時的な共通クラスへのポインタを返す.同時に、Qtに従って、WidgetDataクラスを追加しました.それはいくつかのデータを配置しています.私はこのクラスの具体的な役割をよく理解していません.まず、Widget状態に関するデータを盛るクラスと理解しています.WidgetとWidgetPrivateで参照され、同時にオブジェクトを指しているので、データを修正するのは同期しています.
コードは実は多くなくて、規則があって、恐らくあなたは見終わった後にいくつか疑問があって、ここで、私は私の疑問と解答をここに置いて、あなたもそう思っているかどうかを見ます: Object,Object Private,Object Dataの3つはいったいどんな関係ですか. INVOKE_METHOD_PUBLICマクロ展開後のq_func()関数ではなぜstatic_castはd_のようにfunc()のreinterpret_cast? なぜq_ptrの初期化はObjectdのthisポインタで?特定のクラス ではなく
私の理解:
問題1に対して、Objectは実はその抽象基類とそれ自身が一つになって、その抽象基類はObjectDataに対応して、自分はObjectPrivateに対応します.プログラムの中でコードの注釈を打つ地方、あなたは見てみることができて、ObjectDataを取り除いて、q_ptrをObjectPrivateに移動し、d_ptrタイプをObjectPrivate*に変更する.不適切なコンパイルに成功し、正しく実行できます.しかし、中国語でよく推敲すれば、データポインタd_ptrはどのようにある具体的なクラスのタイプであることができて、汎用的な概念を失いました.
問題2についてstatic_castの役割の1つは親子クラス間で変換することであり、親タイプポインタから子タイプポインタに変換するのは安全ではないが、Qtがこのようにしたのは理解できない.
質問3に対して、これこそq_だと思います.ptrが理解しにくい重要な原因は、私はインターネットで多くの資料を調べたが、例外はなく、図示の例ではq_ptrの初期化はすべて具体的な共通クラスのthisで値を割り当てます.これはよく理解できます.これは多態の概念ではありませんか.親クラスのポインタで初期化されたサブクラスのポインタを指し、必要に応じてstatic_castをサブクラスタイプに変換すると、何の問題も感じず、完璧です.しかし、Qtはそうではなく、q_に対してptrは、すべてQObjectのthisポインタで初期化されていますが、問題はありませんか?自分でプログラムを書いてテストして、初期化された親ポインタstatic_をcastをサブクラスポインタに、変換後のポインタで関数を呼び出します.普通の関数が呼び出された場合、ポインタがどんなタイプなのか、そのタイプの自分の関数を落とすか、親の関数を継承するか、虚関数が呼び出された場合、ポインタがどんなクラスで初期化されたのか、呼び出されたのはそのクラスの関数です.今、私のプログラムを比較してから、Qtソースコードでq->関数の文字を探してみると、これらの関数(推測)はすべて普通の関数で、、、、残り、あ、わかりました...
終わりました.観賞ありがとうございます.
コードを貼り付けます.
/*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で参照され、同時にオブジェクトを指しているので、データを修正するのは同期しています.
コードは実は多くなくて、規則があって、恐らくあなたは見終わった後にいくつか疑問があって、ここで、私は私の疑問と解答をここに置いて、あなたもそう思っているかどうかを見ます:
私の理解:
問題1に対して、Objectは実はその抽象基類とそれ自身が一つになって、その抽象基類はObjectDataに対応して、自分はObjectPrivateに対応します.プログラムの中でコードの注釈を打つ地方、あなたは見てみることができて、ObjectDataを取り除いて、q_ptrをObjectPrivateに移動し、d_ptrタイプをObjectPrivate*に変更する.不適切なコンパイルに成功し、正しく実行できます.しかし、中国語でよく推敲すれば、データポインタd_ptrはどのようにある具体的なクラスのタイプであることができて、汎用的な概念を失いました.
問題2についてstatic_castの役割の1つは親子クラス間で変換することであり、親タイプポインタから子タイプポインタに変換するのは安全ではないが、Qtがこのようにしたのは理解できない.
質問3に対して、これこそq_だと思います.ptrが理解しにくい重要な原因は、私はインターネットで多くの資料を調べたが、例外はなく、図示の例ではq_ptrの初期化はすべて具体的な共通クラスのthisで値を割り当てます.これはよく理解できます.これは多態の概念ではありませんか.親クラスのポインタで初期化されたサブクラスのポインタを指し、必要に応じてstatic_castをサブクラスタイプに変換すると、何の問題も感じず、完璧です.しかし、Qtはそうではなく、q_に対してptrは、すべてQObjectのthisポインタで初期化されていますが、問題はありませんか?自分でプログラムを書いてテストして、初期化された親ポインタstatic_をcastをサブクラスポインタに、変換後のポインタで関数を呼び出します.普通の関数が呼び出された場合、ポインタがどんなタイプなのか、そのタイプの自分の関数を落とすか、親の関数を継承するか、虚関数が呼び出された場合、ポインタがどんなクラスで初期化されたのか、呼び出されたのはそのクラスの関数です.今、私のプログラムを比較してから、Qtソースコードでq->関数の文字を探してみると、これらの関数(推測)はすべて普通の関数で、、、、残り、あ、わかりました...
終わりました.観賞ありがとうございます.