Qt学习记录5
Qt; C++ 11; Qt父子窗体; Qt父子窗体间信息传递; Qt信号与槽; 函数指针;
学习Qt将近2个月了,现在对学习所得进行记录。本文是log2000计划的一部分
实验环境:
Qt5.8.0 支持C++ 11
ubuntu 14.04 64bit
在记录connect函数之前,现需要一些预备知识。
①成员函数指针
首先看一段代码
#include <iostream>
using namespace std;
class Person {
public:
void sayHello(){
cout<<"你好"<<" ";
printf("%d\n",&Person::sayHello);
}
virtual void sayName(){
cout<<"我没有名字"<<" ";
printf("%d\n",&Person::sayName);
}
};
class Child : public Person {
public:
void sayHello(){
cout<<"你好"<<" ";
printf("%d\n",&Child::sayHello);
}
virtual void sayName(){
cout<<"我是小明"<<" ";
printf("%d\n",&Child::sayName);
}
};
typedef void (*FunctionPointer)();
typedef void (Person::*PersonMemberFunctionPointer)();
typedef void (Child::*ChildMemberFunctionPointer)();
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;
}
程序输出:
Starting /home/pc/build-1-Desktop_Qt_5_8_0_GCC_64bit-Debug/1...
你好 4197112 【作者注:someone.sayHello();数字为输出的地址】
你好 4197112 【作者注:虽然是xiaoming,但同样调用的是someone.sayHello();数字为输出的地址】
你好 4197348 【作者注:xiaoming.sayHello();数字为输出的地址】
你好 4197112 【作者注:虽然是xiaoming,但同样调用的是someone.sayHello();数字为输出的地址】
我没有名字 1 【作者注:someone.sayName();数字为输出的地址】
我是小明 1 【作者注:xiaoming.sayName();数字为输出的地址】
/home/pc/build-1-Desktop_Qt_5_8_0_GCC_64bit-Debug/1 exited with code 0
分析上面的代码,其中
typedef void (*FunctionPointer)();
是普通函数指针,typedef void (Person::*PersonMemberFunctionPointer)();
是成员函数指针- 函数
runfuncName
中如果不适用typedef,那么必须PersonMemberFunctionPointer func
这么定义,可是由于使用了typedef,只需要Person::*func
,而void (Person::*func)()
为参数形式调用时的用法。 - 函数
runfuncName
中看出,通过函数调用时要通过“对象(obj->* func)()”这么调用。成员函数指针之所以要通过对象调用是因为形参中默认多了this指针,也就是成员函数sayHello的形参中 - 因为sayHello不是虚函数,所以
(xiaoming.*pp)();
是调用的Person类而不是Child类的sayHello。而runfuncName(&xiaoming,pp);
也是因为sayHello不是虚函数,故调用的仍是Person类。
②成员变量指针
看一段代码
#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>
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;
}
程序输出:
Starting /home/pc/build-2-Desktop_Qt_5_8_0_GCC_64bit-Debug/2...
1 【作者注:a.x=1】
1 【作者注:a.x=1】
1 【作者注:a.x=1】
1 【作者注:a.x=1】
/home/pc/build-2-Desktop_Qt_5_8_0_GCC_64bit-Debug/2 exited with code 0
分析上面的代码,其中
void func(A obj, int A::* p)
是成员变量指针普通调用法,看详细定义:cout<<obj.*p<<endl;
看到‘.’了吧void func2(A * obj, int A::* p)
是指针调用法,看详细定义:cout<<obj->*p<<endl;
看到‘->’了吧template <class T>
是模板调用法,非本次讨论重点typedef int A::* MemberPointer;
定义类型名(将定义的变量名改为类型名)pV = &A::x ;
没有默认传this指针,这个pV为任何A类对象从这个对象首地址到这个成员变量x的偏移量
③函数指针
看一段代码
#include <iostream>
using namespace std;
void hello(){
cout<<"abc"<<endl;
}
int abc(int x){
return x+1;
}
typedef void (*pHello)();
int main(int argc, char *argv[])
{
//1
int (*fAbc)(int);//int (*fAbc)(int axc);
fAbc=&abc;
cout<<(*fAbc)(1)<<endl;
//2
typedef int (*pF)(int);//should be with that pHello line above, but for the sake or understanding, put it here.
pF y;
y=&abc;
//pF y=&abc; is also ok
cout<<(*y)(1)<<endl;
//3
void (*pf)(void);
pf = &hello;
(*pf)();
/*pf=hello
pf()*/is also ok
//4
pHello p = &hello;
(*p)();
return 0;
}
程序输出:
Starting /home/pc/build-3-Desktop_Qt_5_8_0_GCC_64bit-Debug/3...
2
2
abc
abc
/home/pc/build-3-Desktop_Qt_5_8_0_GCC_64bit-Debug/3 exited with code 0
分析上面的代码,其中
- //1中对于函数指针的声明为
int (*fAbc)(int);
,后面括号中的int也可以写成int xxx,即int (*fAbc)(int axc);
- //1中定义了一个指针变量fAbc,它是一个指向某种函数的指针,这种函数参数是一个int型,返回值是int类型。
- //1中对应的赋值方式为
fAbc=&abc;
- //1中对应的的调用方式为
(*fAbc)(1);
- //2中对于函数指针的声明为
typedef int (*pF)(int);
虽然与//1很相似,但//2的优点是更加直观方便 - //2中定义了一种pF的类型,并定义这种类型为指向某种函数的指针,这种函数以一个int为参数并返回int类型
- //2中对应的赋值方式为
pF y=&abc;
- //中对应的调用方式为
(*y)(1)
- //3和//4都大同小异
visitor tracker