【总结】connect的研究
来源:互联网 发布:ssm框架项目源码 编辑:程序博客网 时间:2024/06/03 17:11
1.函数指针
#include <iostream>
using namespace std;
void hello(){
cout<<"abc"<<endl;
}
int abc(int x){
return x+1;
}
typedef void (*pHello)();.........这一行就是typedef的函数指针funcpointer,其实他们就是替代关系,看懂了就
int main(int argc, char *argv[]) 好说了,没看懂就觉得很深奥,*pHello就是代替了hello,那么这个指针就应该
{ 指向hello,*phello=&hello;
//int (*fAbc)(int axc);
//fAbc=&abc;
//cout<<(*fAbc)(1)<<endl;
void (*pf)();
pf = &hello;
//pf = hello;
(*pf)();
//pf();
pHello p = &hello;
(*p)();
return 0;
}
/*
typedef int (*pF)(int); ............这个也是函数指针,这个int必须写上去标明我这里有一个参数。
pF y; 其余和上面差不多。
y=&abc;
cout<<(*y)(1)<<endl;
*/
2.成员变量指针
#include <iostream>
using namespace std;
class A{
public:
int x;
};
void func(A obj, int A::* p){//MemberPointer p
cout<<obj.*p<<endl;
}
void func2(A * obj, int A::* p){
cout<<obj->*p<<endl;
}
template <class T> ...........c++函数模版,根据T类型来决定函数的类型避免重复编程
void func3(T * obj, int T::* p){
cout<<obj->*p<<endl;
}
typedef int A::* MemberPointer;.........成员变量指针 替代关系
int main(int argc, char *argv[])
{
MemberPointer pV;
//成员变量指针的定义
//等价于int A::* pV;
pV = &A::x ;
A a;
a .* pV=1;//等价于a.x=1;
cout << a .* pV << endl;
func(a,pV);
func2(&a,pV);
func3(&a,pV);
return 0;
}
3.比较难以理解的部分,成员函数指针
#include <iostream>
using namespace std;
class Person {
public:
void sayHello(){
cout<<"hello"<<" ";
printf("%d\n",&Person::sayHello);
}
virtual void sayName(){
cout<<"I have no name"<<" ";
printf("%d\n",&Person::sayName);
}
};
class Child : public Person {
public:
void sayHello(){
cout<<"Hello"<<" ";
printf("%d\n",&Child::sayHello);
}
virtual void sayName(){
cout<<"I am XIAOMING"<<" ";
printf("%d\n",&Child::sayName);
}
};
//typedef void (*FunctionPointer)();
typedef void (Person::*PersonMemberFunctionPointer)();....相比于函数指针,就多了一个部分.
typedef void (Child::*ChildMemberFunctionPointer)(); class_name::这个是域名。
void runfuncName(Person * obj, void (Person::*func)() ){//PersonMemberFunctionPointer func
(obj ->* func)();
}
int main(int argc, char *argv[])
{
Person someone;
Child xiaoming;
PersonMemberFunctionPointer pp;
pp = &Person::sayHello;
(someone .* pp)();
//等价于 (&someone ->* pp)();
//也等价于 someone.sayHello();
(xiaoming.*pp)();
//pp=&Child::sayHello;(不能运行,需要强制转换)
ChildMemberFunctionPointer cp = &Child::sayHello;
(xiaoming.*cp)();
runfuncName(&xiaoming,pp);
PersonMemberFunctionPointer pp2 = &Person::sayName;
(someone.*pp2)();
(xiaoming.*pp2)();//必须是公开继承,才有权限
//pp2 = &Child::sayName;(不能运行,需要强制转换)
return 0;
}
总而言之,typedef就是一个替换的过程,只要知道了替换的规则,再看懂应该就不难了。
那么接下来就看我们的connect代码。
#include <iostream>
using namespace std;
//第四步才看
class A;
class B;
typedef void (A::*Apointer)();.....成员函数指针typedef
typedef void (B::*Bpointer)();
//typedef Apointer A::* Signal;
//第一步开始看
class A {
public:
void (A::*click)();
void onClicked(){
cout<<"use my onclicked "<<endl;
}
//第四步才看
B* slotObj;
void TreatClickEvent(){
(slotObj->*(Bpointer)click)();
}
};
//第三步才看
class B {
public:
int x=5;
void onClicked(){
cout<<" use B onclicked the value of X "<<x<<endl;
}
};
//第一步开始看:复习成员变量指针
void runMemberVariblePointer(A * obj, int A::* pMember) {
cout<<obj->*pMember<<endl;
}
//第一步开始看:复习成员函数指针
void runfuncName(A * obj, void (A::*func)()){
(obj->*func)();
}
//第一步看:组合成员变量指针和成员函数指针
void runfuncPointer(A * obj, void (A::*( A::*pfunc ))()){ //Apointer A::* pfunc
(obj->*(obj->*pfunc))();
}
//typedef void (A::*Apointer)();
//第二步才看
//typedef void (A::*(A::*Signal))();
typedef Apointer A::* Signal; ...Apointer就是typedef转换,这里使用了二个typedef
void connect(A* a, Signal signal, Apointer slot){ //void (A::*slot)()
a->*signal = slot;
}
//第三步才看
void connect(A* a, Signal signal, Bpointer slot){
a->*signal = (Apointer) slot;
}
//第四步才看
void connect(A* a, Signal signal, B* b, Bpointer slot){
a->*signal = (Apointer) slot;
a->slotObj = b;
}
int main(int argc, char *argv[])
{
//第一步、理解信号的本质:成员函数指针类型的特殊成员变量
//第二步、连接A本身的信号与槽
A a;
runfuncName(&a,&A::onClicked);
connect(&a,&A::click,&A::onClicked);//a.click = &A::onClicked;
(a.*a.click)();
runfuncPointer(&a,&A::click);
//第三步:连接A的信号到B的槽
B b; B * fb = &b;
connect(&a, &A::click, &B::onClicked);//a.click = (void (A::*)())&B::onClicked;
(a.*a.click)();
(b.*(Bpointer)a.click)();//(fb->*(Bpointer)a.click)();
//第四步:完善连接A的信号到B的槽
connect(&a, &A::click,
fb, &B::onClicked);
a.TreatClickEvent();
return 0;
}
这段代码实现了A,B之间的连接,使用自己的connect函数,而不是QObject的函数;
这段代码注释很清晰了,只需要看懂前面三个,这个代码应该不太难,我就指出几个部分需要看一下的
class A {
public:
void (A::*click)();
void onClicked(){
cout<<"use my A onclicked "<<endl;
}
//第四步才看
B* slotObj;
void TreatClickEvent(){
(slotObj->*(Bpointer)click)();
}
};
我们看class A的定义,里面有void (A::click)这个就是singal的所在,在这里我觉得就是桥梁的
作用。slotobj是为了让信号准确找到相应的槽。
void runfuncPointer(A * obj, void (A::*( A::*pfunc ))()){ //Apointer A::* pfunc
(obj->*(obj->*pfunc))();
}
runfuncPointer(&a,&A::click); 出现了,这个函数,就是这个用法,然后前面的connect语句
connect(&a,&A::click,&A::onClicked);//a.click = &A::onClicked;
然后就直接执行了本A的onclicked。这个地方是二个运用的结合,所以如果用双重typedef会简便看法。
typedef Apointer A::* Signal;
void connect(A* a, Signal signal, Apointer slot){ //void (A::*slot)()
a->*signal = slot;
}
//第三步才看
void connect(A* a, Signal signal, Bpointer slot){
a->*signal = (Apointer)slot ;
}
//第四步才看
void connect(A* a, Signal signal, B* b, Bpointer slot){
a->*signal = (Apointer) slot;
a->slotObj = b;
}
三个connect的代码在这里,signal为信号,slot为槽。我们这里是模拟的
void (A::*( A::*pfunc ))()
void (A::*click)(); 也是一个替代。
所以signal一般都是click。
那其实connect就是制造一个槽和一个信号,然后将他们连接起来这样的功能
那么Qt里面的QObject的connect的运作方式呢
bRet = connect(m_ViewScene,SIGNAL(itemMoved(CustomItem*,const QPointF&)),this,SLOT(ItemMoved(CustomItem*,const QPointF&)));
SIGNAL()宏和SLOT()宏中的函数的参数一定要严格一致。
SIGNAL( itemMoved(CustomItem*,const QPointF&) ),SIGNAL()中是Custom*,那么SLOT()中就得是CustomItem*,否则connect()返回false,表明信号和槽没有连接成功。
void itemMoved(CustomItem *movedItem, const QPointF &movedFromPosition);
const 在connect()方法中不用出现,可以去掉。
&不可以在connect()方法中去掉,如果信号有&,那么connect()方法中必须出现&才行,否则connect()返回false。
那么我们可以看出,内部细节可能很复杂,但是基本也是这个方式,那么connect的学习还需要自己大量的使用才可以
阅读全文
0 0
- 【总结】connect的研究
- connect研究
- connect研究
- Oracle数据库的CONNECT BY ROWNUM研究
- Qt connect函数的深入研究
- NDK的研究总结
- Can't connect to X11 window server的问题研究
- udp调用connect的作用总结
- 研究方法的一点总结
- 最近研究NFC的总结
- Android研究的一些总结
- 关于研究一个新领域,研究思路的总结
- CONNECT BY用法总结
- iTunes Connect 使用总结
- UDP 调用 connect的作用--4A--个人总结
- 阻塞socket中 read,write,connect的小总结
- UDP 调用 connect的作用--4A--个人总结
- JDBC的效率问题研究和总结
- 读 曹林的《人脸识别与人体动作识别技术及应用》笔记
- Android API 26更新一览表
- dw1000(2)-spi数据通讯
- 28-29.个人练习。
- 反编译apk工具,apk反编译工具Jadx的使用
- 【总结】connect的研究
- 大白话说信息熵概念,入门决策树可关注
- iframe嵌套视频横屏播放
- Yii2使用表单上传文件
- leetcode 62. Unique Paths
- 数据库锁
- 关于自增或自减符号在自变量两侧时,在条件循环语句中变化情况
- asp.net mvc开启sql缓存依赖
- 什么是弧度