前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C/C++编程基础:函数指针

C/C++编程基础:函数指针

作者头像
英雄爱吃土豆片
发布2020-10-29 11:07:49
3510
发布2020-10-29 11:07:49
举报
文章被收录于专栏:英雄爱吃土豆片

在讲函数指针之前,我们需要先理解一个概念:编译器是怎么识别并调用函数的。 众所周知,在C/C++程序编译时,内存有四个功能分区: 1)代码区: 存放函数。 2)数据区: 存放静态数据以及全局变量。 3)堆区 存放指针。 4)栈区 存放局部变量。

既然函数也是被存放在内存中的,那函数肯定也就如同其他数据一样,在内存中占有相应的内存单元,而每个内存单元都有一个入口地址。所以,不难想到,程序在运行期间调用一个函数,必定是先寻到这个函数的入口地址,然后才能执行其对应的功能。我们也就可以通过指针直接指向某个函数的入口地址,从而通过指针调用这个函数,这就是函数指针。

函数指针的使用

普通函数指针: 函数指针和变量指针的使用不太一样,函数指针我们通过如下方式声明:

(函数返回值类型) (指针) (函数的形参列表)

示例程序:

代码语言:javascript
复制
#include <iostream>

using namespace std;

void sayName(string name) {
	cout << "I am " << name << endl;
}

int main() {
	void (*p)(string name) = &sayName;
	
	p("Bob");
		
	return 0;
} 

以上程序运行结果输出:

代码语言:javascript
复制
I am Bob

使一个函数指针指向函数时,我们可以只使用对应函数名赋值,不过在函数名前加取地址符号 & 也是没问题的(建议加上)。

类成员函数指针: 如果要使一个函数指针指向类的 public 成员函数,声明的方法也和普通函数指针有所不同,因为我们需要说明这个类成员函数指针指向的函数属于哪个类:

(函数返回值类型) (类名 :: 指针) (函数形参列表)*

示例程序:

代码语言:javascript
复制
#include <iostream>

using namespace std;

class A {
	public:
		A(string name):name_(name) {}
	
	public:
		void sayName() {
			cout << "I am " << name_ << endl;
		}
		
	private:
		string name_;
};

int main() {
	A a("Alice");
	A b("Bob");
	
	void (A::*p)() = &A::sayName;
	
	(a.*p)();
	(b.*p)();
		
	return 0;
}

以上程序运行结果输出:

代码语言:javascript
复制
I am Alice
I am Bob

在通过类成员函数指针调用时,也和普通函数指针的使用不太一样,因为我们需要说明这个类成员函数指针指向这个类的哪一个对象,因为同一个类的不同实例对象,对应成员函数的执行结果也可能是不同的(应该说可能是相同的,因为大部分情况下都应该是不同的才对)。 调用时语法如下:

(实例对象名 . 类成员函数指针) (实参列表)

上面的程序中,我们定义了一个指向 A 类成员的指针 p , 我们先通过 p 调用了 A 类实例对象 a 的 sayName ;然后我们再通过 p 调用了 A 类实例对象 b 的 sayName 。

并且,函数指针也是支持多态的 。

示例程序:

代码语言:javascript
复制
#include <iostream>

using namespace std;

class A {
	public:
		A(string name):name_(name) {}
	
	public:
		virtual void sayName() {
			cout << "I am " << name_ << endl;
		}
		
	protected:
		string name_;
};

class B:public A {
	public:
		B(string name, string number):A(name), number_(number) {}
		
	public:
		void sayName() {
			cout << "I am " << name_ <<  " and ";
			cout << "My number is " << number_ << endl;
		}
		
	private:
		string number_;
};

int main() {
	A a("Alice");
	A b("Bob");
	B c("Sandy", "123456");
	
	void (A::*p)() = &A::sayName;
	
	(a.*p)();
	(b.*p)();
	(c.*p)();
		
	return 0;
} 

以上程序运行结果输出:

代码语言:javascript
复制
I am Alice
I am Bob
I am Sandy and My number is 123456

上面的程序中,我将 A 的 sayName 函数定义为了虚函数,使新定义的类 B 继承自 A ,并在 B 中实现了与其父类 A 中不同的 sayName 函数。此时的 A 类成员函数指针依旧可以指向其子类 B 的 sayName 函数,并且调用的是 B 中实现的 sayName 函数。

毕。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/10/03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档