c++直接调用函数与通过函数指针调用有什么不一样

作者&投稿:单于昂 (若有异议请与网页底部的电邮联系)
C++两个类如何通过指针相互调用对方的函数?~

交叉引用一般有两种方法
class B ;
class A
{
B* pb ;
void funA() ;
} ;

class B
{
A* pa ;
void funB() ;
}

void A::funA() { pb->funB() ; } // warning of infinite loop here
void B:: funB() { pa->funA() ; } // warning of infinite loop here
这是最常见的方式
------------------------------------------------
但上面方式有个严重的缺陷, 必须要把类的定义和实现分开.这就意味着,
你不能类的实现放在.h中(并被多个.cpp包含), 不然就等着编译器在链接时抱怨"符号重定义"
因为类的定义作用域是单模块, 而函数的定义是扩模块的.
我平时写类库, 最怕的就是为个.h要写个.cpp,文件,太繁琐.

所以可以使用方法2
template
class A
{
B* pb ;
void funA() { pb->funB() ; } // warning of infinite loop here
} ;

class B
{
A* pa ;
void funB() { pa->funA() ; } // warning of infinite loop here
}
这种C++ idiom虽然说要让A引入策略B做为模板参数, 有些"做作"
但是交叉引用这种设计很多时候隐含着, 你的class A确实需要依赖策略B中的语义.
所以模板并不是单纯解决"双重引用"这个机制而诞生的, 而是class A在概念上对于策略B的自然依赖. 只是策略B除了用class B初始化, 还可以用其他类初始化

一、
在学习arm过程中发现这“指针函数”与“函数指针”容易搞错,所以今天,我自己想一次把它搞清楚,找了一些资料,首先它们之间的定义:
1、指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针
类型标识符 *函数名(参数表)
int *f(x,y);

首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。
表示:
float *fun();
float *p;
p = fun(a);
注意指针函数与函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数名前面的指针*号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。
来讲详细一些吧!请看下面
指针函数:
当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。
格式:
类型说明符 * 函数名(参数)
当然了,由于返回的是一个地址,所以类型说明符一般都是int。
例如:int *GetDate();
int * aaa(int,int);
函数返回的是一个地址值,经常使用在返回数组的某一元素地址上。

int * GetDate(int wk,int dy);

main()
{
int wk,dy;
do
{
printf(Enter week(1-5)day(1-7)
);
scanf(%d%d,&wk,&dy);
}
while(wk5||dy7);
printf(%d
,*GetDate(wk,dy));
}

int * GetDate(int wk,int dy)
{
static int calendar[5][7]=
{
{1,2,3,4,5,6,7},
{8,9,10,11,12,13,14},
{15,16,17,18,19,20,21},
{22,23,24,25,26,27,28},
{29,30,31,-1}
};
return &calendar[wk-1][dy-1];
}
程序应该是很好理解的,子函数返回的是数组某元素的地址。输出的是这个地址里的值。



2、函数指针是指向函数的指针变量,即本质是一个指针变量。
 int (*f) (int x); /* 声明一个函数指针 */
 f=func; /* 将func函数的首地址赋给指针f */

指向函数的指针包含了函数的地址,可以通过它来调用函数。声明格式如下:
类型说明符 (*函数名)(参数)
其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明笔削和它指向函数的声明保持一致。
指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。
例如:
void (*fptr)();
把函数的地址赋值给函数指针,可以采用下面两种形式:
fptr=&Function;
fptr=Function;
取地址运算符&不是必需的,因为单单一个函数标识符就标号表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
可以采用如下两种方式来通过指针调用函数:
x=(*fptr)();
x=fptr();
第二种格式看上去和函数调用无异。但是有些程序员倾向于使用第一种格式,因为它明确指出是通过指针而非函数名来调用函数的。下面举一个例子:

void (*funcp)();
void FileFunc(),EditFunc();

main()
{
funcp=FileFunc;
(*funcp)();
funcp=EditFunc;
(*funcp)();
}

void FileFunc()
{
printf(FileFunc
);
}

void EditFunc()
{
printf(EditFunc
);
}

程序输出为:
FileFunc
EditFunc

主要的区别是一个是指针变量,一个是函数。在使用是必要要搞清楚才能正确使用

二、指针的指针
指针的指针看上去有些令人费解。它们的声明有两个星号。例如:
char ** cp;
如果有三个星号,那就是指针的指针的指针,四个星号就是指针的指针的指针的指针,依次类推。当你熟悉了简单的例子以后,就可以应付复杂的情况了。当然,实际程序中,一般也只用到 二级指针,三个星号不常见,更别说四个星号了。
指针的指针需要用到指针的地址。
char c='A';
char *p=&c;
char **cp=&p;
通过指针的指针,不仅可以访问它指向的指针,还可以访问它指向的指针所指向的数据。下面就是几个这样的例子:
char *p1=*cp;
char c1=**cp;
你可能想知道这样的结构有什么用。利用指针的指针可以允许被调用函数修改局部指针变量和处理指针数组。

void FindCredit(int **);

main()
{
int vals[]={7,6,5,-4,3,2,1,0};
int *fp=vals;
FindCredit(&fp);
printf(%d
,*fp);
}

void FindCredit(int ** fpp)
{
while(**fpp!=0)
if(**fpp<0) break;
else (*fpp)++;
}

首先用一个数组的地址初始化指针fp,然后把该指针的地址作为实参传递给函数FindCredit()。FindCredit()函数通过表达式**fpp间接地得到数组中的数据。为遍历数组以找到一个负值,FindCredit()函数进行自增运算的对象是调用者的指向数组的指针,而不是它自己的指向调用者指针的指针。语句(*fpp)++就是对形参指针指向的指针进行自增运算的。但是因为*运算符高于++运算符,所以圆括号在这里是必须的,如果没有圆括号,那么++运算符将作用于二重指针fpp上。

三、指向指针数组的指针
指针的指针另一用法旧处理指针数组。有些程序员喜欢用指针数组来代替多维数组,一个常见的用法就是处理字符串。

char *Names[]=
{
Bill,
Sam,
Jim,
Paul,
Charles,
0
};

main()
{
char **nm=Names;
while(*nm!=0) printf(%s
,*nm++);
}

先用字符型指针数组Names的地址来初始化指针nm。每次printf()的调用都首先传递指针nm指向的字符型指针,然后对nm进行自增运算使其指向数组的下一个元素(还是指针)。注意完成上述认为的语法为*nm++,它首先取得指针指向的内容,然后使指针自增。

函数指针也可以指向类的成员函数的,调用是需要通过类实例来调用:

typedef int (CTranSession::*BillProc )(char*,char*);
int CTranSession::GetAllBillDetailCDMA( char *sphone,char *scalltime )
{
    int ret = 0;
    BillProc p[8];
    
    p[0] = CDMA_GetMonth;
    p[1] = CDMA_GetLocal;
    p[2] = CDMA_GetWander;
    p[3] = CDMA_GetMessage;
    p[4] = CDMA_Get1XMessage;
    p[5] = CDMA_Get1XFlux;
    p[6] = CDMA_GetMRBT;
    p[7] = CDMA_GetEvVoice;
    
    for( int i = 0;i < 8 && ret != -1;ret = (this->*p[i++])( sphone,scalltime ));
    
    return ret;
}


如果函数create被修饰为静态函数是可以调用的。你可以看看该函数前面是否有static关键词。


PHP直接调用函数和调用另外一个文件中的函数的区别
\/\/如果是PHP文件中的函数,唯一的区别是:先引入外部文件,然后直接调用。\/\/如果是外部类文件中的函数,需要引入,然后new 对象后,再调用该对象的函数。$msg=test_msg();function test_msg(){echo "";}\/\/调用外部文件中的函数\/\/首先引入文件include_once 'file.php';$msg=test_msg();function ...

函数的间接调用与直接调用的区别?
1: 直接调用,就是直接来调用这个函数。比如 function(A); 这就是直接调用了。2: 间接调用,顾名思义,就是通过别人来调用这个函数,而不是当前的这段代码来调用。比如我想要调用function(A)的功能, 但仅仅 function(A)的功能又不够。 而此时还需要用到 function(B)中的一些...

Javascript中调用一个函数,使用new或者直接调用有什么区别
new的调用有两种方式:静态方法或普通的方法。如果是调用静态方法,和直接调用没区别;如果调用的是普通方法,则方法内可以使用非静态变量或者非静态方法。而通过直接调用是静态方法,该方法必须是静态方法。

c++直接调用函数与通过函数指针调用有什么不一样
函数指针也可以指向类的成员函数的,调用是需要通过类实例来调用:typedef int (CTranSession::*BillProc )(char*,char*);int CTranSession::GetAllBillDetailCDMA( char *sphone,char *scalltime ){ int ret = 0; BillProc p[8]; p[0] = CDMA_GetMonth; p[1] = CDMA_Get...

c语言中怎么调用函数
1、直接调用,这种函数一般没有返回值,或者不需要返回值 如 printf("你好,可以直接调用printf函数的!")2、表达式调用,比如对于用户写的一个求最大值函数int max(int a,int b),一般有返回值 如 c=max(6,9) 也就是要用一个量来接收函数返回来的值。3、参数调用,同样对于上面的max 如...

可以直接调用函数吗?
可以调用。C语言最基本的模块为函数,任意函数都可以调用其它任意一个函数,包括函数本身。1、自定义函数调用其它自定义函数的例子:include <stdio.h>void fun1(int a)\/\/自定义函数fun1。{ printf("%d\\n",a);}void fun2(int m, int n)\/\/自定义函数fun2。{ fun1(m); fun1(n)...

vba的函数调用与取得返回值
1、直接调用或者call 过程名 call 函数名就可以了,比如 Private Sub CommandButton1_Click()MsgBox "你调用了CommandButton1_Click过程"End Sub Private Sub CommandButton2_Click()Call CommandButton1_Click End Sub 2、如果有参数的话需要带上参数,比如 Private Sub CommandButton1_Click()Call ...

...被调函数运行时内部变量存在哪里,和直接调用函数有什么区别?_百度...
在C语言中,数组名代表数组的首地址,同样函数名代表了函数的首地址,因此在赋值时,直接将函数指针指向函数名就行了。因此函数指针调用vs直接调用,占用的存储空间都是一样的。相当于数组指针和数组名的关系,指向的都是同一个数组。局部变量存在函数体里面,比如转换成8086汇编(示意):func: 定义变量 ...

django中如何调用函数和类(2023年最新解答)
django的views直接传一段html代码调用模板中的js函数。 有三种方法: 1,在模版中的html文件中嵌入含有这个函数的js文件或者直接加到html里面. 2,在js中通过ajax访问打开一个链接,比如\/admin\/url?key=value,那么在admin.py中的url方法中这样keyvlaue=request.GET.get('key',None)来获取这个value,然后py做一番处理...

在VBA中如何调用过程与函数?
一、直接调用或者call 过程名 call 函数名就可以了,比如 Private Sub CommandButton1_Click()MsgBox "你调用了CommandButton1_Click过程"End Sub Private Sub CommandButton2_Click()Call CommandButton1_Click End Sub 二、如果有参数的话需要带上参数,比如 Private Sub CommandButton1_Click()Call ...

静海县19682256993: c++直接调用函数与通过函数指针调用有什么不一样 -
刘步安胃: 如果函数create被修饰为静态函数是可以调用的.你可以看看该函数前面是否有static关键词.

静海县19682256993: 通过函数指针调用函数 c++ -
刘步安胃: 这个例子,有一个误导.其实例1中,参数不是普通指针,是二级指针,其实是相当于:**name 这样就可以修改*name的值,这是二级指针的典型应用.如果第二个例子中这样调用:swap(&point_1,&point_2); 并且函数这样写:void swap(int **p1,int **p2){int *temp;temp=*p1;*p1=*p2;*p2=temp;}这就和例子1的效果一样了.误导在于:int *name[]其实是一个二级指针

静海县19682256993: C/C++函数调用的几种方式及函数名修饰规则以 -
刘步安胃: 要将函数名作为参数,需要使用函数指针.函数指针的定义格式为 ret_type (*var_name)(arg_list); 表示返回值为ret_type,参数列表为arg_list的函数指针var_name. 如 int (*p)(int,int); 表示返回值为int,参数为两个int型的函数指针p. 以函数指针作为形参,即可实现函数名作为参数,由另一个函数调用. 如void func(int (*a)(int)) { int r = 100l; (*a)(r); } 即可传入函数指针,并以r为参数,调用该指针指向的函数.

静海县19682256993: C语言中,函数和函数指针,效率上差很多吗? -
刘步安胃: 1.直接调用函数,编译的时候,被调函数的地址(或偏移)直接写入指令;2.使用函数指针时,运行期从内存中取地址,在使用call指令 理论上,这存在效率差异.根据你的系统环境:服务器、PC还是嵌入式处理器、单片机等,及你的代码的时间敏感程度:如时序严格的驱动还是MS,等等因素,自己可以判断使用.还有一点需要强调:使用函数指针是为了获得某种灵活或模型(C++编译器内部大量使用函数指针),所以,这是一种平衡.

静海县19682256993: C++怎么在成员函数里调用指向成员函数的函数指针 -
刘步安胃: 1.一个指向外部函数的指针声明为: void(*pf)(char*,constchar*); void strcpy(char* dest,constchar* source); pf=strcpy; 2.一个指向类A成员函数的指针声明为: void(A::*pmf)(char*,constchar*);

静海县19682256993: 请教C++中函数型指针和指针型函数的用法和区别,谢谢 -
刘步安胃: 1 函数指针变量 在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址.我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数.然后通过指针变量就可以找到并调用...

静海县19682256993: C++两个类之间的成员函数怎么相互调用,怎么老是报错. -
刘步安胃: 1) 将需要调用的成员函数设为static 类型,如:在前述例子2中,将class Test2 成员函数Compare 定义前加上static 如下(黑体为改变之处):class Test2{//….int static __cdecl Compare(const void* elem1, const void* elem2) //成员函数.//其...

静海县19682256993: C/C++函数调用的几种方式 -
刘步安胃: 在C语言中,可以用以下几种方式调用函数: 1. 函数表达式: 2. 函数语句: 3. 函数实参; 4. 函数的嵌套调用; 网页链接

静海县19682256993: C++函数调用方式有哪些 -
刘步安胃: 我们知道,调用函数时,计算机常用栈来存放函数执行需要的参数,由于栈的空间大小是有限的,在windows下栈是向低地址扩展的数据结构,是一块连续的内存区域.这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,windows...

静海县19682256993: c++ 函数调用和直接展开为什么差别这么大 -
刘步安胃: 这个主要和代码底层原理有关,函数调用被编译器编译后,会比代码展开(内联或者宏调用)多个跳转指令,也就是代码执行要从一个内存位置跳转到另一个位置去执行;函数调用还有另外的性能开销,那就是函数栈,函数调用需要开辟出栈空间,还要对函数参数进行压栈、出栈操作.关键的问题是,如果只是进行一次函数调用,所有的这些性能开销加起来,和代码展开相比其实也没有什么差别(性能测试除外),但是需要代码展开的都是要反复、多次调用执行的小代码段,多次的执行相比起来函数调用和代码展开的性能差别就很大了.

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网