⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 functionpointer.html

📁 关于 C++ 的历史无须我来介绍了
💻 HTML
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>

  
  <link rel="stylesheet" href="css/stdlayout.css" type="text/css">

  
  <link rel="stylesheet" href="css/print.css" type="text/css">

  
  <meta content="text/html; charset=gb2312" http-equiv="content-type">

  
  <title>函式指标</title>
</head>


<body>

<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>

<h1><a href="CppGossip.html">C++
Gossip: 函式指标</a></h1>

程式在执行时,函式本身在记忆体中也占有一个空间,而函式名称本身也就是指向该空间位址的参考名称,当呼叫函式名称时,程式就会去执行该函式名称所指向的
记忆体空间中之指令。 <br>

<br>

您可以宣告函式指标,并让它与某个函式指向相同的空间,函式指标的宣告方式如下所示: <br>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">传回值型态
(*指标名称)(传递参数); </span><br>

</div>

<br>

一个函式型态由传回值型态与参数列决定,不包括函式名称,一个函式指标可指向具有相同型态的函式,也就是具有相同传回值型态和参数列的函式。<br>

<br>

下面这个程式是个简单的示范,它以函式指标ptr来取得函式foo()的位址,使用它来呼叫函式,将与使用foo()来呼叫函式具有相同的作用,程式以整
数方式显示两个的记忆体空间是相同的: <br>

<br>

<pre>#include &lt;iostream&gt; <br>using namespace std; <br><br>int foo(); <br><br>int main() { <br>    int (*ptr)() = 0; <br><br>    ptr = foo; <br><br>    foo(); <br>    ptr(); <br><br>    cout &lt;&lt; "address of foo:" <br>         &lt;&lt; (int)foo &lt;&lt; endl; <br>    cout &lt;&lt; "address of foo:" <br>         &lt;&lt; (int)ptr &lt;&lt; endl; <br><br>    return 0; <br>} <br><br>int foo() { <br>    cout &lt;&lt; "function point" &lt;&lt; endl; <br><br>    return 0; <br>}</pre>

<span class="postbody"><br>

执行结果:</span><br>

<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">

  <tbody>

    <tr>

      <td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">function point<br>

function point<br>

address of foo:4199502<br>

address of foo:4199502</span></small><span style="color: rgb(255, 255, 255);"><br>

      </span></td>

    </tr>

  
  </tbody>
</table>

<br>

如果函式带有参数,则函式指标本身的宣告也必须指定相同的参数型态与个数,下面这个程式用来显示重载函式会分别占据不同的记忆体空间: <br>

<br>

<pre>#include &lt;iostream&gt; <br>using namespace std; <br><br>int foo(int, int); <br>char foo(int, char); <br><br>int main() { <br>    int (*ptr1)(int, int) = 0; <br>    char (*ptr2)(int, char) = 0; <br><br>    ptr1 = foo; // get address of foo(int, int) <br>    ptr2 = foo; // get address of foo(int, char) <br><br>    ptr1(1, 2); <br>    ptr2(3, 'c'); <br><br>    cout &lt;&lt; "address of foo(int, int): " <br>         &lt;&lt; (int)ptr1 &lt;&lt; endl; <br>    cout &lt;&lt; "address of foo(int, char): " <br>         &lt;&lt; (int)ptr2 &lt;&lt; endl; <br><br>    return 0; <br>} <br><br>int foo(int n1, int n2) { <br>    cout &lt;&lt; "foo(int, int): " <br>         &lt;&lt; n1 &lt;&lt; "\t" &lt;&lt; n2 <br>         &lt;&lt; endl;<br><br>    return 0; <br>} <br><br>char foo(int n, char c) { <br>    cout &lt;&lt; "foo(int, char): " <br>         &lt;&lt; n &lt;&lt; "\t" &lt;&lt; c <br>         &lt;&lt; endl;<br><br>    return c; <br>}</pre>

<span class="postbody"><br>

执行结果:</span><br>

<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">

  <tbody>

    <tr>

      <td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">foo(int, int):
1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2<br>

foo(int, char): 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c<br>

address of foo(int, int): 4199548<br>

address of foo(int, char): 4199648</span></small><span style="color: rgb(255, 255, 255);"><br>

      </span></td>

    </tr>

  
  </tbody>
</table>

<br>

由于在宣告函式指标时已指定了参数列的资料型态与个数,所以虽然在指定ptr1与ptr2时都使用foo函式名称,但程式仍可以自动判别出我们是要指定哪
个过载函式的位址。 <br>

<br>

来看看一个应用的例子,假设您要撰写一个排序sort()函式,您希望排序时可以由大至小,也可以由小至大,比较简单的作法是在sort()上加上一个额
外的参数,可以传入常数或列举,例如如果指定1的话就由大至小,指定0的话就由小至大,这需要在函式中加上额外的判断,为了简化sort()的撰写,可以
传入一个函式位址,函式中就无需额外的判断,例如:<br>

<ul>

  <li>sort.h</li>

</ul>

<pre>void swap(int&amp;, int&amp;);<br>bool larger(int a, int b);<br>bool smaller(int a, int b);<br>void sort(int*, int, bool (*compare)(int, int));</pre>

<br>

<ul>

  <li>sort.cpp</li>

</ul>

<pre>#include "sort.h";<br><br>void swap(int &amp;a, int &amp;b) {<br>    int t = a; <br>    a = b; <br>    b = t;<br>}<br><br>bool larger(int a, int b) {<br>     return a &gt; b;<br>}<br><br>bool smaller(int a, int b) {<br>     return a &lt; b;<br>}<br><br>void sort(int* arr, int length, bool (*compare)(int, int)) { <br>    int flag = 1; <br><br>    for(int i = 0; i &lt; length-1 &amp;&amp; flag == 1; i++) { <br>        flag = 0; <br>        for(int j = 0; j &lt; length-i-1; j++) { <br>            if(compare(arr[j+1], arr[j])) { <br>                swap(arr[j+1], arr[j]); <br>                flag = 1; <br>            } <br>        } <br>    } <br>}</pre>

<br>

<ul>

  <li>main.cpp</li>

</ul>

<pre>#include &lt;iostream&gt; <br>#include "sort.h"<br>using namespace std; <br><br>int main() { <br>    int number1[] = {3, 5, 1, 6, 9};<br>    sort(number1, 5, larger);<br>    cout &lt;&lt; "大的在前 ";<br>    for(int i = 0; i &lt; 5; i++) {<br>        cout &lt;&lt; number1[i] &lt;&lt; " ";<br>    }<br>    cout &lt;&lt; endl;<br><br>    int number2[] = {3, 5, 1, 6, 9};<br>    sort(number2, 5, smaller);<br>    cout &lt;&lt; "小的在前 ";<br>    for(int i = 0; i &lt; 5; i++) {<br>        cout &lt;&lt; number2[i] &lt;&lt; " ";<br>    }<br>    cout &lt;&lt; endl;<br> <br>    return 0; <br>}</pre>

<br>

<span class="postbody">
执行结果:</span><br>

<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">

  <tbody>

    <tr>

      <td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">大的在前 9 6 5 3 1<br>

小的在前 1 3 5 6 9</span></small><span style="color: rgb(255, 255, 255);"><br>

      </span></td>

    </tr>

  
  </tbody>
</table>

<br>

在函式中,不必理会传入的实际函式,只要呼叫compare()就可以了,在这个例子中,您的sort()上的函式指标宣告有些难以阅读,您可以使用
typedef,定义一个比较容易阅读的名称,例如:<br>

<ul>

  <li>sort.h</li>

</ul>

<pre>typedef bool (*CMP)(int, int);<br>void swap(int&amp;, int&amp;);<br>bool larger(int a, int b);<br>bool smaller(int a, int b);<br>void sort(int*, int, CMP);</pre>

<br>

<ul>

  <li>sort.cpp</li>

</ul>

<pre>#include "sort.h"<br><br>void swap(int &amp;a, int &amp;b) {<br>    int t = a; <br>    a = b; <br>    b = t;<br>}<br><br>bool larger(int a, int b) {<br>     return a &gt; b;<br>}<br><br>bool smaller(int a, int b) {<br>     return a &lt; b;<br>}<br><br>void sort(int* arr, int length, CMP compare) { <br>    int flag = 1; <br><br>    for(int i = 0; i &lt; length-1 &amp;&amp; flag == 1; i++) { <br>        flag = 0; <br>        for(int j = 0; j &lt; length-i-1; j++) { <br>            if(compare(arr[j+1], arr[j])) { <br>                swap(arr[j+1], arr[j]); <br>                flag = 1; <br>            } <br>        } <br>    } <br>}</pre>

<br>

可以看到,重新使用typedef定义CMP名称后,函式比较容易阅读的多了。<br>

<br>

您也可以宣告函式指标阵列,例如:<br>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">bool
(*compare[10])(int, int);</span><br>

</div>

<br>

上面这个宣告产生具有10个元素的阵列,可以储存10个sort函式型态的位址,不过这样的宣告实在难以阅读,可以使用typedef来改进:<br>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">typedef bool
(*CMP)(int, int);</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">

<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">CMP compare[10];</span><br>

</div>

<br>

可以看到这次的宣告比较容易阅读了。<br>

</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -