
首先 函数指针是指向一组同类型的函数的指针;而类成员函数我们也可以相似的认为,它是指向同类中同一组类型的成员函数的指针,当然这里的成员函数更准确的讲应该是指非静态的成员函数。前者是直接指向函数地址的,而后者我们从字面上也可以知道 它肯定是跟类和对象有着关系的。
函数指针实例:
代码如下:
typedef int (p)(int,int);//定义一个接受两个int型且返回int型变量的函数指针类型
int func(int x,int y)
{
printf("func:x=%d,y=%d/n",x,y);
return (x<yx:y);
}
int main()
{
p fun=func;//定义函数指针并给它赋上一个函数指针
cout<<"min:"<<(fun)(4,5)<<endl;//为什么fun需要用()扩起来呢因为的运算符优先级比()低,如果不用()就成了(fun())
return 0;
}
而“指向类成员函数的指针”却多了一个类的区别:
class A
{
public:
int func(int x,int y)
{
printf("A::func:x=%d,y=%d/n",x,y);
return (x<yx:y);
}
};
typedef int (A::p)(int,int);//指针名前一定要加上所属类型类名 A::的限定
int main()
{
p fun=&A::func;
A a; //因为成员函数地址的解引用必须要附驻与某个对象的地址,所以我们必须创建某个对象。
cout<<"min:"<<(afun)(4,5)<<endl;
return 0;
}
嘿嘿。。只是用起来 感觉怪怪滴。
接下来 我们可以再扩展一下下:
代码如下:
#include <tcharh>
#include <iostream>
#include <stdioh>
using namespace std;
class A
{
public:
int func1(int x,int y)
{
printf("A::func:x=%d,y=%d/n",x,y);
return (x<yx:y);
}
virtual int func2(int x,int y)
{
printf("A::func:x=%d,y=%d/n",x,y);
return (x>yx:y);
}
};
class B:public A
{
public:
virtual int func2(int x,int y)
{
printf("B::func:x=%d,y=%d/n",x,y);
return (x+y);
}
};
typedef int (A::p)(int,int);//指针名前一定要加上所属类型类名 A::的限定
typedef int (B::p0)(int,int);
int main()
{
A a; //因为成员函数地址的解引用必须要附驻与某个对象的地址,所以我们必须创建某个对象。
p fun=&A::func1;
cout<<(afun)(4,5)<<endl;
cout<<(bfun)(4,5)<<endl<<endl;
fun=&A::func2;
cout<<(afun)(4,5)<<endl;//请注意这里调用的是虚函数,嘿嘿 还真神奇 类成员函数指针也支持多态。
cout<<(bfun)(4,5)<<endl<<endl;
//fun=&B::func2; //这样式错误滴,因为不存在派生类的"指向类成员函数的指针"到基类的"指向类成员函数的指针"的隐式转换
fun=(int (A::)(int,int))&B::func2;//应该进行强制转换
cout<<(afun)(4,5)<<endl;
cout<<(bfun)(4,5)<<endl<<endl;
p0 fun0=&B::func2;
cout<<(afun)(4,5)<<endl;
cout<<(bfun)(4,5)<<endl<<endl;
fun0=&A::func2; //正确,因为这里进行了隐式转换
cout<<(afun)(4,5)<<endl;
cout<<(bfun)(4,5)<<endl<<endl;
//从上面我们不难发现 指向类成员函数的指针基类和派生类的关系和指向类对象的指针基类和派生类的关系完全相反,
//基类成员函数的布局被认为是派生类成员函数布局的一个子集
return 0;
}
接下 是有关模板类的类成员函数指针的使用
实例如下:
代码如下:
#include <tcharh>
#include <iostream>
#include <stdioh>
using namespace std;
class A
{
public:
int func(int x,int y)
{
printf("A::func : x=%d,y=%d/n",x,y);
return (x<yx:y);
}
};
class B
{
public:
int func(int x,int y)
{
printf("B::func : x=%d,y=%d/n",x,y);
return (x>yx:y);
}
};
template<class T>
class C
{
public:
T c;
void Print()
{
int (T::p)(int,int)=&T::func;
(cp)(4,5);
}
};
int main()
{
C<A> ca;
C<B> cb;
caPrint();
cbPrint();
return 0;
}
从上面 可以很清晰地看到。。其实它和普通的模板没有什么区别。。只不过将限定名称该为参数名酒OK啦。。。
1、C++是从早期的C语言逐渐发展演变来的,与C语言相比,它在求解问题方法上最大的改进是( B )。
A. 面向过程 B 面向对象 C 安全性 D 复用性
2、下列关于this指针的叙述中,正确的是( )
A任何与类相关的函数都有this指针
B类的成员函数都有this指针
C类的友元函数都有this指针
D类的非静态成员函数才有this指针
3、若有以下类Z声明,函数fStatic的正确定义是( )。
class Z
{ int a;
public:
void fStatic(Z&)static;
};
Avoid Z::fStatic(Z &objZ){ objZa=0; }
Bvoid Z::fStatic(Z &objZ){ a= objZa; }
Cvoid Z::fStatic(Z &objZ){ a=0; }
Dvoid Z::fStatic(Z &objZ){ Z::a=0; }
4、在C++中,关于下列设置缺省参数值的描述中,( C )是正确的。
A.不允许设置缺省参数值;
B.只能在函数的定义中指定参数的缺省值;
C.在指定了缺省值的参数右边,不能出现没有指定缺省值的参数;
D.设置缺省参数值时,必须全部都设置;
5、关于友元函数的描述中,错误的是( D )。
A.友元函数说明在类体内
B.友元函数不是成员函数
C.友元函数必须用对象来引用
D.友元函数可以直接访问类中的私有成员
6、对于类,下面哪个是不正确的( D )。
A 类是对象的设计蓝图
B 使用关键字Class创建类结构
C 类被声明后,类名成为类型名并且可以用来声明变量
D 类与结构体相同,它们之间没有区别
7、下列是构造函数的特点,( C )是错误的。
A构造函数是一种成员函数,它具有一般成员函数的特点。
B构造函数的名称与其类名相同。
C构造函数必须指明其类型。
D一个类中可以定义一个或多个构造函数。
8、已知:p是一个指向类A数据成员m的指针,a是类A的一个对象。在给m赋值为5的下列表达式中,( D )是正确的。
A ap=5
B a->p=5
C ap=5
D ap=5
9、下面对静态数据成员的描述中,正确的选项是( C )。
A静态成员可以在类体内进行初始化
B静态数据成员不可以被类的对象调用
C静态数据成员可以直接用类名调用
D静态数据成员不可以直接用类名调用
10、下列关于new运算符的描述中,错误的是( B )。
Anew运算符组成的表达式的值是地址值
B创建对象时不调用构造函数
C用它创建的对象须用delete来删除
D可用它来创建动态的对象和对象数组
2和3题目本身有问题,问问出题的人:
关于2,this是指向类对象本身的指针,和任何成员包括函数扯不上关系,不过通过this指针可以引用除静态成员以外的任何成员
关于3,fStatic是静态函数,不能引用任何非静态成员,因为这些成员只存在于类对象中。
用静态成员和静态函数的好处是保证实例的唯一性,不是属于某个对象,而是属于这个类的。 这样可以减少消耗,对于许多函数都要调用的函数可以将其设为静态函数,内存只有一份拷贝实例。
静态函数会被自动分配在一个一直使用的存储区,直到退出应用程序实例,避免了调用函数时压栈出栈,速度快很多。
在某个类A中声明一个static int number;初始化为0。这个number就能被所有A的实例共用。在A的构造函数里加上number++,在A的析构函数里加上number--。那么每生成一个A的实例,number就加一,每销毁一个A的实例,number就减一,这样,number就可以记录程序中共生成了多少个A的实例。
这只是静态成员的一种用法而已。
静态类中的成员加入static修饰符,即是静态成员可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员因为静态成员存在于内存,所以非静态成员可以直接访问类中静态的成员
静态变量都在全局数据分配内存,包括后面将要提到的静态局部变量,对于一个完整的程序,在内存中的分布情况如下 代码区- 全局数据区- 堆区- 栈区
一般由new产生出来的动态数据存放在堆区,函数内部的自动变量存放在栈区。 自动变量一般会随着函数的退出而释放空间,静态数据(包括函数内部的静态局部变量)也存放在全局数据区,全局数据区的数据不会因为函数的退出而释放空间。
Static静态变量不能为其它文件所用(这个区别于extern的)
静态数据成员只能而且必须在类外初始化
静态成员函数里面没有隐藏this指针。
非静态成员函数可以访问静态数据成员。 静态成员函数不能访问非静态数据成员。
关于静态成员函数,可以总结为以下几点:
出现在类体外的函数定义不能指定关键字static;
静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
非静态成员函数可以任意地访问静态成员函数和静态数据成员;
静态成员函数不能访问非静态成员函数和非静态数据成员;
由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
调用静态成员函数,可以用成员访问 *** 作符()和(->)为一个类的对象或指向类对象的指针调用静态成员函数
class A
{
public:
static void staticmember(){cout<<"static"<<endl;} //static member
void nonstatic(){cout<<"nonstatic"<<endl;} //nonstatic member
virtual void virtualmember(){cout<<"virtual"<<endl;};//virtual member
};
int main()
{
A a;
//static成员函数,取得的是该函数在内存中的实际地址,而且因为static成员是全局的,所以不能用A::限定符
void (ptrstatic)() = &A::staticmember;
//nonstatic成员函数 取得的是该函数在内存中的实际地址
void (A::ptrnonstatic)() = &A::nonstatic;
//虚函数取得的是虚函数表中的偏移值,这样可以保证能过指针调用时同样的多态效果
void (A::ptrvirtual)() = &A::virtualmember;
//函数指针的使用方式
ptrstatic();
(aptrnonstatic)();
(aptrvirtual)();
}
static关键字不仅可以用来修饰变量,还可以用来修饰函数。在使用 static 关键字修饰变量时,我们称此变量为静态变量。静态变量的存储方式与全局变量一样,都是静态存储方式。静态变量属于静态存储方式,属于静态存储方式的变量却不一定就是静态变量。
在C语言中,static关键字的作用如下:
在修饰变量的时,static修饰的静态局部变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。
static修饰全局变量的时,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是extern外部声明也不可以。
static修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。Static修饰的局部变量存放在全局数据区的静态变量区。
C++的static用法:
面向过程程序设计中的static和面向对象程序设计中的static。前者应用于普通变量和函数,不涉及类;后者主要说明static在类中的作用。
在类中,static可以用来修饰静态数据成员和静态成员方法。
静态数据成员:
静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。
静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。
静态数据成员既可以通过对象名引用,也可以通过类名引用。
静态成员函数:
静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员。
非静态成员函数有this指针,而静态成员函数没有this指针。
静态成员函数主要用来方位静态数据成员而不能访问非静态成员。
#include <iostreamh>
class ok
{
int a;
static int s;//声明静态数据成员
public:
ok(int a);
static void show();//声明静态成员函数
};
int ok::s=0;//定义并初始化静态数据成员
ok::ok(int a)
{
this->a=a;
s+=a; //非静态成员函数可以访问静态数据成员
}
void ok::show() //静态成员函数的实现
{
//cout<<a<<endl; //错误代码,a是非静态数据成员
cout<<"s="<<s<<endl;
}
void main()
{
ok cat(2);
catshow();
ok dog(3);
dogshow();
ok::show();
}
/------------------------------------------------------------
○静态成员之间可以相互访问,如静态成员函数访问静态数据成员和静态成员函数;
○静态成员函数没有this指针。无法访问属于类对象的非静态数据成员和非静态成员函数,
○非静态成员函数可以访问静态成员函数和静态数据成员;
○静态成员函数不能访问非静态成员函数和非静态数据成员;
○由于没有this指针的额外开销,因此静态成员函数与类的非静态函数相比速度上会有少许的增长;
○非静态成员函数总是具体的属于某个类的具体对象,this是缺省的;
-------------------------------------------------------------/
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)