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

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

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

函数指针的使用

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

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

示例程序:

#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;
} 

以上程序运行结果输出:

I am Bob

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

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

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

示例程序:

#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;
}

以上程序运行结果输出:

I am Alice
I am Bob

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

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

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

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

示例程序:

#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;
} 

以上程序运行结果输出:

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 函数。

猜你喜欢

转载自blog.csdn.net/weixin_45711556/article/details/108907964