本文目录索引 1,C++中怎么获取类的成员函数的函数指针 2,如何在c++中声明指向对象的成员函数的函数指针? 3,c++怎样通过函数指针调用成员函数 4,如何理解变量,指针,引用? 5,C++成员函数指针问题 6,静态成员函数怎么引用该类中的非静态成员函数 7,非
本文目录索引
- 1,C++中怎么获取类的成员函数的函数指针
- 2,如何在c++中声明指向对象的成员函数的函数指针?
- 3,c++怎样通过函数指针调用成员函数
- 4,如何理解变量,指针,引用?
- 5,C++成员函数指针问题
- 6,静态成员函数怎么引用该类中的非静态成员函数
- 7,非静态成员函数如何来访问静态成员函数
- 8,C++怎么定义一个指向函数的指针?
- 9,函数指针和指针函数有什么区别?
- 10,c语言指针函数和函数指针有什么不同
1,C++中怎么获取类的成员函数的函数指针
虾米意思?是指类的成员变量是否可以指向类中的成员函数吗?如果这样子的,类的成员函数指针就是用来起这个作用,mfc消息路由机制也是机遇此原理。#include <stdio.h>class A{public: A() \/\/ Ctor { m_pfn1 = A::foo; \/\/ 有没有取地址符号一样 m_pfn2 = &A::bar; (this->*m_pfn1)(); (this->*m_pfn2)(0); } void foo(){printf("foo\n");} \/\/ 类函数 virtual void bar(int){printf("bar\n");} void (A::*m_pfn1)(); \/\/ 类函数指针成员变量 void (A::*m_pfn2)(int); \/\/ 类函数指针成员变量};int _tmain(int argc, _TCHAR* argv[]){ \/\/ 1. 类函数指针成员变量的使用 A a; A* p = &a; (a.*(a.m_pfn1))(); (a.*(a.m_pfn2))(0); \/\/ 多态 (p->*(p->m_pfn1))(); (p->*(p->m_pfn2))(0); \/\/ 多态 \/\/ 2. 类外函数指针变量的使用 typedef void (A::*MemFunPtr)(); MemFunPtr memPtr = &A::foo; (a.*memPtr)(); (p->*memPtr)(); return 0;}\r\n补充:\r\n->* 和.* 是C++新增加的操作符号,专用类成员指针变量取址(成员函数指针,成员变量指针)\r\n
2,如何在c++中声明指向对象的成员函数的函数指针?
并不存在指向对象成员的函数指针。 指向对象成员的指针称为成员指针,和函数指针并不等价,也就是不能当作函数指针使用。 struct A{ void foo() { } void goo() { }};void (A::*p)(); // p就是一个A类对象中没有参数返回void的成员函数的成员指针int main(){ p = &A::foo; // 然后可以用这种写法对它赋值。 p = &A::goo; int A::*q; // 数据成员同样可以有成员指针 q = &A::x; q = &A::y; A a; (a.*p)(); // 成员指针的用法,必须和对象配套使用 a.*q = 1;} 对于必须使用函数指针的情况,可能需要获得静态成员函数的函数指针(静态成员函数是可以正常获得函数指针的)。并在调用时,把对象的地址作为参数传递。
3,c++怎样通过函数指针调用成员函数
函数存放在内存的代码区域内,它们同样有地址.如果我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址。
1、函数指针的定义方式:data_types (*func_pointer)( data_types arg1, data_types arg2, ...,data_types argn);
例如: int (*fp)(int a); //这里就定义了一个指向函数(这个函数参数仅仅为一个int类型,函数返回值是int类型)的指针fp。
例子:
int test(int a)
{
return a;
}
int main(int argc, const char * argv[])
{
int (*fp)(int a);
fp = test;
cout<<fp(2)<<endl;
return 0;
}
注意,函数指针所指向的函数一定要保持函数的返回值类型,函数参数个数,类型一致。
4,如何理解变量,指针,引用?
你问的这个话题太大。关于指针和引用要讲的东西很多。
我的理解:
指针: 其实指针这个概念在谭浩强的这本书上是这样说的,指针就是地址,指针值就是地址值。指针变量就是存放指针的
变量,所以一定不要将指针与指针变量搞混淆了。指针仅仅是一个地址值,而指针变量就是存放指针(也就是地址的变量)
指针的定义:
例如整型指针: int *p;p是一个指向int类型数据的指针变量。里面存放的地址(也就是指针)是一个int类型变量的地址。指针变量时
有类型的,例如p的类型就是int *表示p是一个指向int类型的指针变量。如何知道一个指针变量的类型呢,最简单的方法就是去掉变
量定义语句中的变量名,剩下的部分就是其类型,这种方法适用于所有的变量定义,例如int a;a的类型是int 。 int b[10];b的类
型是int[]表示是一个数组(关于数组类型这里不谈,因为这个问题很微妙,其实在c、c++中没有数组类型这个概念,包括函数类型也
是一样的),int *c;c的类型是int *。int ** d;d的类型就是int **;所以通过这种方法来判断一个变量的类型是很方便的。
说道指针变量,我们必须说到得有几个方面。
1.指针类型。
这个很重要,一个指针是有类型的,也就是一个地址是有类型的。具体说是某一个地址会指向不同类型的数据,这是不一样的,例如
int *p;p是指向int型数据。 double*p1;p1是指向double型数据。但是p和p1本身在内存中占用的空间是4个字节(对于32位的系统来说
),如果是在TC中编译c程序,应该是2个字节了(dos操作系统是16位的)。有人说地址不就是一个值吗,类似于0xfffdddcc这样的地址
数值,为什么还分什么类型呢,我要说的是这个关系很大。我们知道指针是有运算的,int *p=&a;那么p++到底加了多少呢,不要以为
是将p里面的地址值加了1,这是完全想当然。实际上加了sizeof(int)这么多个字节。也就是说加了一个int元素应该占用的字节,这
样在数组中我们可以通过这种方式从上一个元素很方便的让指针变量指向下一个元素。p+5的话实际上是加了p+sizeof(int)*5这么多
个字节。 另外一点事指针的类型决定了当指针解引用的时候其所以指向的内存单元中的二进制数据如何解释的问题。例如int *p=&a;
那么(*p)取得的数字就是一个整型数据,如果(*((char *)p))得到的就是一个字符型数据了。p本来指向的是int型数据(有4个字节)的
首地址,如果将其强制转换为一个指向char类型的指针变量,那么在解引用的时候只取第一个字节的数据,并将其解释为一个ascii码
代表的字符。 还有如果是一个指向函数的指针变量,我们可以通过此指针变量直接调用函数。例如int(*function)(int);此时
function指向一个函数,此函数具有一个int参数,返回一个int值。那么通过指针可以这样调用该类型的函数了int a=function
(100); 或者int a=(*function)(100);其实要不要解引用都是可以的。不过以前是需要解引用的,现在c标准规定这两种方法都可以。
总的来说指针的类型很重要。
2.指针与数组。
我们向一个函数传递数组的时候一般是传递数组名,我们知道数组名是一个代表数组中第一个元素的地址并且数组名是不可以当左值
的。其实你又没有想过数组名到底是什么呢。有人说其实数组名就是一个指针常量,是一个不可以改变的指针常量。例如:int a[10]
={1,2,3,4,5,6,7,8,9,10}; 那么a可能的类型是int * const a;注意const的位置(关于指针常量和常量指针,这个以后说),那么这种
说法到底对不对呢。我们可以通过sizeof运算符来计算某一种数据类型占用的存储空间。例如 sizeof(10)的值为4,注意这里我都假
设在32位的操作系统上面编译。其实sizeof(10)和sizeof(int)是一样的,仅仅是求这种类型的数据占用多少内存空间,而不是说具体
的某个数据占用的空间,因为对于10这个文字常量来说根本不会占用内存空间的,其实随着程序直接编码到源程序中的,不存在分配
内存的问题。那么我们这样计算sizeof(a);是不是如我们所愿得到的是4呢。 结果可能会有意外,因为其值是sizeof(int)*10也就是
40个字节,显然这个字节数是整个数组占用的字节数。而不是int *类型的指针变量占用的字节数,我们知道一个地址只占用4个字节
那么这说明数组名绝对不是简单的int*类型。但是数组确实具有int*的特性。例如int*p=a;这是不会报错的。而且在函数之间传递的
时候也是采用这样的方式:
void print(int b[10]){}
调用函数:
print(a);
或者:
print(&a[0]);
都是一样的。
注意在某一个函数内对形参进行sizeof:
void print(int c[100])
{
sizeof(c); // 此时表达式的结果是4,而不是100。因为这里int c[100]与int *c是一样的,c不是数组名(数组名是不能作为左值
的)
}
3. 指针与函数
一个指针可以指向一个函数,指针可以作为函数参数,函数可以返回一个指针类型的数据。
指向函数的指针: 指向函数的指针,实际上此指针就是函数代码的入口地址。我们可以通过这样的方式调用函数。例如:
void print1(int x)
{
cout<<"hello "<<x<<endl;
}
void print2(int y)
{
cout<<"hello "<<y<<endl;
}
那么在main函数中可以这样写:
void (*p)(int)=print1;//函数名代表函数入口地址值,和数组一样,print1不仅仅是一个地址。
p(10);
p=print2;
p(20);
这都是可以的,另外我们可以通过一个指针数组存放指向函数的指针:
void (*aa[2])(int)={print1,print2};
for(int i=0;i<2;i++)
{
aa[i](i); //通过函数指针循环调用里面的函数
}
关于各种指向函数指针的声明,请自己查阅有关资料。
引用:
引用相当于别名,其实你直接将其当做一个别名就可以了。引用与指针的区别: 引用必须初始化,而且初始化之后不可更改,指针
却可以。
5,C++成员函数指针问题
看一下这个代码,应该对你有帮助。类方法的指针 要被调用,需要这个类的一个对象来调用
class A
{
public:
int draw(int x) {return x*2;}
};
typedef int (A::*FUNC)(int);
class B
{
public:
void get(FUNC pfunc, A a, int x)
{
(a.*pfunc)(x);
printf("%d\n", (a.*pfunc)(x));
}
};
void main()
{
A a;
B b;
b.get(&A::draw, a, 10);
}
6,静态成员函数怎么引用该类中的非静态成员函数
最佳答案,感觉有些没说明白,是说静态成员函数调用了原类的普通成员函数拷贝构造函数和析构函数么?修改了下代码,大致可以看清: #include using namespace std; class Myclass { private: int m; // 非静态数据成员 static int n; // 静态数据成员 public: Myclass(); // 构造函数 Myclass(Myclass &r); // 拷贝构造函数 static int getn(Myclass a); // 静态成员函数 ~Myclass(); // 析构函数 }; Myclass::Myclass() { m = 10; cout << "调用构造函数" << endl; } Myclass::Myclass(Myclass &r) { m = r.m; cout << "调用拷贝构造函数" << endl; } Myclass::~Myclass() { cout << "调用析构函数" << endl; } int Myclass::getn(Myclass a) { cout << a.m << endl; // 通过类间接使用 非静态数据成员 return n; // 直接使用 静态数据成员 } int Myclass::n = 100; // 静态数据成员初始化 void main() { Myclass app1; cout << app1.getn(app1) << endl; // 利用对象引用静态函数成员 cout << Myclass::getn(app1) << endl; // 利用类名引用静态函数成员 system("pause"); } 这里还有个改来的例子,原例子是讲静态成员函数调用静态成员变量的。网址:网页链接 我在这里再构造一个普通成员函数,用静态成员函数调用它,碰到普通成员函数只能通过对象调用的问题,因此在静态成员函数中定义了一个默认值的对象(面积是0.不会计数图形个数),但是每次这个对象销毁后(即这个静态成员函数调用之后)系统会调析构函数,使图形计数减1,所以我在这里强行加1.最终编译运行是可以的,可以参考下。 #include using namespace std; class CRectangle { private: int w=0, h=0; static int totalArea; //矩形总面积 static int totalNumber; //矩形总数 public: CRectangle() {}; CRectangle(int w_, int h_); CRectangle(CRectangle & r); ~CRectangle(); void PrintCRectangle(); static void PrintTotal(); }; CRectangle::CRectangle(int w_, int h_) { w = w_; h = h_; totalNumber++; //有对象生成则增加总数 totalArea += w * h; //有对象生成则增加总面积 } CRectangle::CRectangle(CRectangle & r) { totalNumber++; totalArea += r.w * r.h; w = r.w; h = r.h; } CRectangle::~CRectangle() { totalNumber--; //有对象消亡则减少总数 totalArea -= w * h; //有对象消亡则减少总而积 } void CRectangle::PrintCRectangle() { cout totalNumber totalArea << endl; } void CRectangle::PrintTotal() { CRectangle a; /*cout << totalNumber << "," << totalArea << endl;*/ a.PrintCRectangle(); totalNumber++; } //必须在定义类的文件中对静态成员变量进行一次声明 //或初始化,否则编译能通过,链接不能通过 int CRectangle::totalNumber = 0; int CRectangle::totalArea = 0; int main() { CRectangle r1(1, 1); CRectangle *r2 = new CRectangle(2, 2); CRectangle r3(r1); //cout << CRectangle::totalNumber; //错误,totalNumber 是私有 CRectangle::PrintTotal(); r2->PrintTotal(); r3.PrintTotal(); delete r2; CRectangle::PrintTotal(); r1.PrintTotal(); r3.PrintTotal(); return 0; } 再改一个版本,仿照最佳答案,在静态成员函数中参数可以是类的对象,则在函数中不再定义类的对象,直接使用对象调用类的普通成员函数。由于这样做在调用静态成员函数时会对类对象初始化,调用构造函数(调用拷贝构造函数),则会对面积加和,计数会加1,而此函数调用结束,还会调用析构函数,会将面积减小,计数减1,所以会在下面的一些函数中加一些处理。最终结果,和上面是对得上的。 #include using namespace std; class CRectangle { private: int w=0, h=0; static int totalArea; //矩形总面积 static int totalNumber; //矩形总数 public: CRectangle() {}; CRectangle(int w_, int h_); CRectangle(CRectangle & r); ~CRectangle(); void PrintCRectangle(); static void PrintTotal(CRectangle a); }; CRectangle::CRectangle(int w_, int h_) { w = w_; h = h_; totalNumber++; //有对象生成则增加总数 totalArea += w * h; //有对象生成则增加总面积 } CRectangle::CRectangle(CRectangle & r) { totalNumber++; totalArea += r.w * r.h; w = r.w; h = r.h; } CRectangle::~CRectangle() { totalNumber--; //有对象消亡则减少总数 totalArea -= w * h; //有对象消亡则减少总而积 } void CRectangle::PrintCRectangle() { cout totalNumber totalArea << endl; totalArea += this->w * this->h; totalNumber++; } void CRectangle::PrintTotal(CRectangle a) { totalArea -= a.w * a.h; totalNumber--; /*cout << totalNumber << "," << totalArea << endl;*/ a.PrintCRectangle(); } //必须在定义类的文件中对静态成员变量进行一次声明 //或初始化,否则编译能通过,链接不能通过 int CRectangle::totalNumber = 0; int CRectangle::totalArea = 0; int main() { CRectangle r1(1, 1); CRectangle *r2 = new CRectangle(2, 2); CRectangle r3(r1); //cout << CRectangle::totalNumber; //错误,totalNumber 是私有 CRectangle::PrintTotal(r1); r2->PrintTotal(*r2); r3.PrintTotal(r3); delete r2; CRectangle::PrintTotal(r1); r1.PrintTotal(r3); r3.PrintTotal(r3); return 0; } 上述代码还可以改成: void CRectangle::PrintCRectangle() { cout totalNumber totalArea << endl; //totalArea += this->w * this->h; //totalNumber++; } void CRectangle::PrintTotal(CRectangle a) { totalArea -= a.w * a.h; totalNumber--; /*cout << totalNumber << "," << totalArea << endl;*/ a.PrintCRectangle(); totalArea += a.w * a.h; totalNumber++; } 即,只在PrintTotal函数中处理面积和计数的变化。 如果上面程序中将拷贝构造函数去掉,则结果会出错。
7,非静态成员函数如何来访问静态成员函数
加上关键字static,该数据成员就是类内的静态数据成员。先举一个静态数据成员的例子。
//Example 5#include <iostream.h>class Myclass;int Myclass::Sum=0;//定义并初始化静态数据成员Myclass::Myclass(int a,int b,int c)void Myclass::GetSum()void main()
可以看出,静态数据成员有以下特点:
对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷 贝,由该类型的所有对象共享访问。也就是说,静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共 用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新;
静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义。在Example 5中,语句int Myclass::Sum=0;是定义静态数据成员;
静态数据成员和普通数据成员一样遵从public,protected,private访问规则;
因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它;
静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式为:
<数据类型><类名>::<静态数据成员名>=<值>
类的静态数据成员有两种访问形式:
<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名>
如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员 ;
静态数据成员主要用在各个对象都有相同的某项属性的时候。比如对于一个存款类,每个实例的利息都是相同的。所以,应该把利息设为存款类的静态数据成员。这 有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区的内存,所以节省存储空间。第二,一旦利息需要改变时,只要改变一次, 则所有存款类对象的利息全改变过来了;
同全局变量相比,使用静态数据成员有两个优势:
静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性;
可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能;
2、静态成员函数
与静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都是类的内部 实现,属于类定义的一部分。 普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this 是缺省的。如函数fn()实际上是this->fn()。但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指 针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。 下面举个静态成员函数的例子。
//Example 6#include <iostream.h>class Myclass;int Myclass::Sum=0;//定义并初始化静态数据成员Myclass::Myclass(int a,int b,int c)void Myclass::GetSum() //静态成员函数的实现void main()
关于静态成员函数,可以总结为以下几点:
出现在类体外的函数定义不能指定关键字static;
静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
非静态成员函数可以任意地访问静态成员函数和静态数据成员;
静态成员函数不能访问非静态成员函数和非静态数据成员;
由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以直接使用如下格式:
<类名>::<静态成员函数名>(<参数表>)
调用类的静态成员函数。
===============================================================================================
static静态变量声明符。 在声明它的程序块,子程序块或函数内部有效,值保持,在整个程序期间分配存储器空间,编译器默认值0。
是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性。
2、为什么要引入static?
函数内部定义的变量,在程序执行到它的定义处时,编译器为它在栈上分配空间,大家知道,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此变量的值保存至下一次调用时,如何实现? 最容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不仅仅受此函数控制)。
3、什么时候用static?
需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见。
4、static的内部机制:
静态数据成员要在程序一开始运行时就必须存在。因为函数在程序运行中被调用,所以静态数据成员不能在任何函数内分配空间和初始化。
这样,它的空间分配有三个可能的地方,一是作为类的外部接口的头文件,那里有类声明;二是类定义的内部实现,那里有类的成员函数定义;三是应用程序的main()函数前的全局数据声明和定义处。
静态数据成员要实际地分配空间,故不能在类的声明中定义(只能声明数据成员)。类声明只声明一个类的“尺寸和规格”,并不进行实际的内存分配,所以在类声明中写成定义是错误的。它也不能在头文件中类声明的外部定义,因为那会造成在多个使用该类的源文件中,对其重复定义。
static被引入以告知编译器,将变量存储在程序的静态存储区而非栈上空间,静态
数据成员按定义出现的先后顺序依次初始化,注意静态成员嵌套时,要保证所嵌套的成员已经初始化了。消除时的顺序是初始化的反顺序。
5、static的优势:
可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。
6、引用静态数据成员时,采用如下格式:
<类名>::<静态成员名>
如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式
来引用静态数据成员。
7、注意事项:
(1)类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致
了它仅能访问类的静态数据和静态成员函数。
(2)不能将静态成员函数定义为虚函数。
(3)由于静态成员声明于类中,操作于其外,所以对其取地址操作,就多少有些特殊
,变量地址是指向其数据类型的指针 ,函数地址类型是一个“nonmember函数指针”。
(4)由于静态成员函数没有this指针,所以就差不多等同于nonmember函数,结果就
产生了一个意想不到的好处:成为一个callback函数,使得我们得以将C++和C-based X W
indow系统结合,同时也成功的应用于线程函数身上。
(5)static并没有增加程序的时空开销,相反她还缩短了子类对父类静态成员的访问
时间,节省了子类的内存空间。
(6)静态数据成员在<定义或说明>时前面加关键字static。
(7)静态数据成员是静态存储的,所以必须对它进行初始化。
(8)静态成员初始化与一般数据成员初始化不同:
初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆;
初始化时不加该成员的访问权限控制符private,public等;
初始化时使用作用域运算符来标明它所属类;
所以我们得出静态数据成员初始化的格式:
<数据类型><类名>::<静态数据成员名>=<值>
(9)为了防止父类的影响,可以在子类定义一个与父类相同的静态变量,以屏蔽父类的影响。这里有一点需要注意:我们说静态成员为父类和子类共享,但我们有重复定义了静态成员,这会不会引起错误呢?不会,我们的编译器采用了一种绝妙的手法:name-mangling 用以生成唯一的标志。
[编辑本段]static 函数
内部函数和外部函数
当一个源程序由多个源文件组成时,C语言根据函数能否被其它源文件中的函数调用,将函数分为内部函数和外部函数。
1 内部函数(又称静态函数)
如果在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,这种函数称为内部函数。
定义一个内部函数,只需在函数类型前再加一个“static”关键字即可,如下所示:
static 函数类型 函数名(函数参数表)
关键字“static”,译成中文就是“静态的”,所以内部函数又称静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件。
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。
2 外部函数
外部函数的定义:在定义函数时,如果没有加关键字“static”,或冠以关键字“extern”,表示此函数是外部函数:
[extern] 函数类型 函数名(函数参数表)
调用外部函数时,需要对其进行说明:
[extern] 函数类型 函数名(参数类型表)[,函数名2(参数类型表2)……];
[案例]外部函数应用。
(1)文件mainf.c
main()
{ extern void input(…),process(…),output(…);
input(…); process(…); output(…);
}
(2)文件subf1.c
……
extern void input(……) /*定义外部函数*/
(3)文件subf2.c
……
extern void process(……) /*定义外部 函数*/
(4)文件subf3.c
……
extern void output(……) /*定义外部函数*/
另外,团IDC网上有许多产品团购,便宜有口碑
8,C++怎么定义一个指向函数的指针?
C++指向函数的指针定义方式为:
返回类型 (*指针名)(函数参数列表),例如 void (*p)(int)是指向一个返回值为void 参数为int类型的函数。
而若想定义一个指向类成员函数的函数指针该怎么定义呢?对成员函数指针的使用。
(1)非静态成员函数
定义方式:返回类型 (类名::*指针名)(函数参数列表)例如void (A::*p)(int)是一个指向A类中成员函数的函数指针。
赋值方式:p=&A::函数名,而一般的函数指针的赋值是p=函数名即可,注意区别。(成员函数必须是public类型的)
调用方式:成员函数指针的调用必须通过类对象进行调用,a.*p(int)即可调用成员函数(该成员函数是public类型的)
(2)静态成员函数
对于静态成员函数的定义和使用方法都与普通函数指针的相同,只是在赋值的时候和非静态成员们函数指针的赋值方法相同。
因为静态成员函数的指针类型是与普通函数指针类型相同的。
9,函数指针和指针函数有什么区别?
函数指针和指针函数的区别:
一、【函数指针】
在程序运行中,函数代码是程序的算法指令部分,它们和数组一样也占用存储空间,都有相应的地址。可以使用指针变量指向数组的首地址,也可以使用指针变量指向函数代码的首地址,指向函数代码首地址的指针变量称为函数指针。
1、函数指针定义
函数类型(*指针变量名)(形参列表);
“函数类型”说明函数的返回类型,由于“()”的优先级高于“*”,所以指针变量名外的括号必不可少,后面的“形参列表”表示指针变量指向的函数所带的参数列表。
例如:
int (*f)(int x);
double (*ptr)(double x); 在定义函数指针时请注意:
函数指针和它指向的函数的参数个数和类型都应该是—致的; 函数指针的类型和函数的返回值类型也必须是一致的。
2、函数指针的赋值
函数名和数组名一样代表了函数代码的首地址,因此在赋值时,直接将函数指针指向函数名就行了。 例如,
int func(int x); /* 声明一个函数 */
int (*f) (int x); /* 声明一个函数指针 */
f=func; /* 将func函数的首地址赋给指针f */
赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。
3、通过函数指针调用函数
函数指针是通过函数名及有关参数进行调用的。
与其他指针变量相类似,如果指针变量pi是指向某整型变量i的指针,则*p等于它所指的变量i;如果pf是指向某浮点型变量f的指针,则*pf就等价于它所指的变量f。同样地,*f是指向函数func(x)的指针,则*f就代表它所指向的函数func。所以在执行了f=func;之后,(*f)和func代表同一函数。
由于函数指针指向存储区中的某个函数,因此可以通过函数指针调用相应的函数。现在我们就讨论如何用函数指针调用函数,它应执行下面三步: 首先,要说明函数指针变量。
例如:int (*f)(int x);
其次,要对函数指针变量赋值。
例如: f=func; (func(x)必须先要有定义)
最后,要用 (*指针变量)(参数表);调用函数。
例如: (*f)(x);(x必须先赋值)
【例】任意输入n个数,找出其中最大数,并且输出最大数值。
main()
{
int f();
int i,a,b;
int (*p)(); /* 定义函数指针 */
scanf("%d",&a);
p=f; /* 给函数指针p赋值,使它指向函数f */
for(i=1;i<9;i++)
{
scanf("%d",&b);
a=(*p)(a,b); /* 通过指针p调用函数f */
}
printf("The Max Number is:%d",a)
}
f(int x,int y)
{
int z;
z=(x>y)?x:y;
return(z);
}
运行结果为:
343 -45 4389 4235 1 -534 988 555 789↙ The Max Number is:4389
二、【指针函数】
一个函数不仅可以带回一个整型数据的值,字符类型值和实型类型的值,还可以带回指针类型的数据,使其指向某个地址单元。
返回指针的函数,一般定义格式为:
类型标识符 *函数名(参数表)
int *f(x,y);
其中x,y是形式参数,f是函数名,调用后返回一个指向整型数据的地址指针。f(x,y)是函数,其值是指针。
如:char *ch();表示的就是一个返回字符型指针的函数,请看下面的例题:
【例】将字符串1(str1)复制到字符串2(str2),并输出字符串2.
#include "stdio.h"
main()
{
char *ch(char *,char *);
char str1[]="I am glad to meet you!";
char str2[]="Welcom to study C!";
printf("%s",ch(str1,str2));
}
char *ch(char *str1,char *str2)
{
int i;
char *p;
p=str2
if(*str2==NULL) exit(-1);
do
{
*str2=*str1;
str1++;
str2++;
}
while(*str1!=NULL);
return(p);
}
通过分析可得:
函数指针是一个指向函数的指针,而指针函数只是说明他是一个返回值为指针的函数, 函数指针可以用来指向一个函数。
10,c语言指针函数和函数指针有什么不同
如楼上所说 。
指针函数 的本质是 函数 ,只是他的返回值 类型 是指针变量。
比如 int * A(int num); 这就是一个 指针函数。
函数指针 是一个 指针变量 ,只不过 他是 指向函数的 指针变量。
比如 有函数定义 如上 int * A(int num); 再有 int (*pf)(int num);
则是 pf = A;就把 函数A的首地址 赋值给 pf 函数指针了。
下一篇:没有了