代码改变世界

菜鸟C++自学笔记【指针】下

2010-10-25 15:44  Terry_龙  阅读(2089)  评论(9编辑  收藏  举报

继续上篇指针未完成的学习任务。

 

  • 指向函数的指针
  • 指向指针的指针
  • 指向指针数组的指针
  • 指向const 变量的指针
  • const 指针变量
  • void 指针
  • 1.指向函数的指针

    指向函数的指针包含函数的地址,可以通过指针调用该函数。下面这种格式声明了一个函数指针:

    int (*fpt)();

     

    指针的名字是fpt。这个特殊的指针指向一个返回整数值并且不接受实参的函数。指针声明必须与指针所指函数的声明相匹配。

    下面的DEMO表明,一个函数指针在不同时段可以具有不同的函数地址:

     

    #include "stdafx.h"
    #include 
    <iostream>

    void FileFunc(),EditFunc();

    int main(int argc, char* argv[])
    {
     
        
    void (*fileTmp)(); //声明一个指针函数 
        fileTmp=FileFunc;  //指向函数的地址
        (*fileTmp)();    //通过指针调用函数


        fileTmp
    =EditFunc;
       (
    *fileTmp)();
        
    return 0;
    }


    void FileFunc(){
        std::cout
    <<"File Function\n";
    }
     
    void EditFunc(){
        std::cout
    <<"Edit Function\n";
    }

     

     

    运行效果如下:

    通过使用函数指针的数组,可以创建一个有限状态机,程序行为取决于变量的值,根据变量值确定程序接下来执行哪个函数。表格驱动的菜单管理程序就是一个有限状态机的例子。

    如下DEMO演示了如何通过4个原型菜单分别显示一条消息:

     

    #include "stdafx.h"
    #include 
    <iostream>

    struct Menu{
        
    char* name;
        
    void (*fn)();
    };

    void FileFunc();
    void EditFunc();
    void ViewFunc();
    void ExitFunc();

    Menu menu[]
    ={
        {
    "File",FileFunc},
        {
            
    "Edit",ExitFunc
        },
        {
            
    "View",ViewFunc
        },
        {
            
    "Exit",ExitFunc
        }
    };

    const int sels=sizeof menu/sizeof(Menu);

    int main(int argc, char* argv[])
    {

        unsigned sel
    =0;
        
    while(sel!=sels){
            
    for (int i=0;i<sels;i++)
            {
                std::cout
    <<i+1<<":"<<menu[i].name<<"\n";
            }
            std::cout
    <<"select:";
            std::cin
    >>sel; 
            
    if(sel<sels+1&&sels>0)
            {
                (
    *menu[sel-1].fn)();
            }
        }
        
    return 0;
    }

    void FileFunc(){
        std::cout
    <<"File Function \n";
    }


    void EditFunc(){
        std::cout
    <<"Edit Function \n";
    }

    void ViewFunc(){
        std::cout
    <<"View Function \n";
    }

    void ExitFunc(){
        std::cout
    <<"Exit Function \n";
    }

     

     

    运行效果:

     

    2.指向指针的指针

    指向指针的指针可能不太容易处理。需要两个星号声明指针。如下所示:

    char** opp;

    可以由此类推,三个四个等多个星星,对应指向几个指针的指针。

    下面有一个DEMO演示如何使用一个被调用函数修改调用函数的局部指针,并处理指针数组:

     

    #include "stdafx.h"
    #include 
    <iostream>

    void FindCredit(float** fpp);
     
    int main(int argc, char* argv[])
    {

        
    float values[]={
            
    34.23,87.33,46.33,-23.44,85.34,0
        };
     
        
    float* fp=values;
        FindCredit(
    &fp);
        std::cout
    <<*fp<<"\n";
        
    return 0;
    }
     

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

     

     

    运行效果如下:

     

    上面程序用数组地址初始化fp 指针,并把fp 指针的地址传递给FindCredit函数,该函数将指向指针的指针作为其唯一形参的实参。FindCredit用**fpp表达式间接地提取数组元素值。FindCredit函数递增调用函数指针向数组的指针,而不是递增自己指向调用函数指针的局部指针,以便在数组的循环访问中查找负值。(*fpp)++;语句的含义是递增指针形参所指定的内容,。而当遇到负值则跳出循环体。程序结束。

    3.指向指针数组的指针

    指向指针的指针的另一种用法是处理指针数组。

    下面的DEMO演示了如何通过指向指针数组的指针打印出数组内容:

     

    #include "stdafx.h"
    #include 
    <iostream>
     
    char* Names[]={
        
    "Bill",
        
    "Sam",
        
    "Jim",
        
    "Charles",
        
    "Donald",
        
    0
    };
     
    int main(int argc, char* argv[])
    {

     
        
    char** nm=Names;
        
    while(*nm!=0){
            std::cout
    <<*nm++<<"\n";
        }
        
    return 0;
    }
     

     

     

    运行效果如下:

    如上代码,把nm 指针初始化为字符指针数组Names的地址。每个std::count调用都传递nm指针所指的字符指针,然后递增指针,指向数组的下一个元素(指针)。

     

    4.指向const变量的指针

    当我们声明一个指向const 变量的指针时,意味着程序不能通过指针修改变量。声明形式如下:

    const char* str;

    任何对str指针所指字符数据的引用必须为只读的。这种用法有几层含义。首先,不能将一个const 变量的地址赋予指针,除非指针按上面的方式声明。此外,如果函数的某个形参被声明为指向一个非const 的变量指针,就不能把const 变量的地址对应该形参的实参传递给函数。看如下DEMO:

     


    #include 
    "stdafx.h"
    #include 
    <iostream>
     

    void cpytoupper(char* s1,const char* s2)
    {
        
    char* s=s1;
        std::cout
    <<"const :"<<s2<<"\n";
         
    }
     
    int main(int argc, char* argv[])
    {
        
        
    char* rcv="terry";
     
    const char snd[]="Hello, terry";
     cpytoupper(rcv,snd);
     std::cout
    <<rcv<<"\n";
     
        
    return 0;
    }
     

     

    运行效果如下:

     

    5.const指针变量

    我们可以定义在初始化后就不能改变自身内容的指针,这种做法可以增加代码的安全性。如果指针永远不用于迭代,换言之,如果这个指针永远保持其初始值,就按下面的方式将其声明为const指针变量:

    char* const ptr=buf;

    这里就不细究了。

     

    6.void 指针

    void 指针可以指向任何类型的变量,其声明方式如下:

    void* vptr;

    任何地址都可以赋给void 指针,除非使用了类型强型转换,否则就不能用void 指针来取出一个变量值。

    关于指针的学习,暂时到这里,以后再回头来加深下理解。