Chinaunix首页 | 论坛 | 博客
  • 博客访问: 13096
  • 博文数量: 3
  • 博客积分: 130
  • 博客等级: 入伍新兵
  • 技术积分: 30
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-03 09:39
文章分类

全部博文(3)

文章存档

2010年(3)

我的朋友
最近访客

分类: C/C++

2010-06-03 15:00:38

C和C++的指针是有区别的:

   C的指针有两种:指向数据,指向函数;

   C++的指针有4种:指向数据,指向函数,指向成员数据和指向成员函数;为什么不分两种,指向数据和指向函 数,这个前2种和后2种不能一对一。可以这么分,指向非成员和指向成员,指向成员的简称成员指针。以下一一说明。

1,指向数据的指针

非常简单。例如:



int a = 100;
int *p = &a;
cout<<*p<<endl;


2,指向函数的指针

函数名可以看成是一个单身函数对象,取值后是函数的入口地址,如:


void foo(int a)
{
}


foo看成是一个类型是void (int)的单身对象,但是对名字foo取值后,它会退化成相应的指针类型void (*)(int)。注意那个括号不能少。当然如果对foo取地址也是这个类型(取两次?没考虑过~~哇靠~太绝了吧)。

所以指向函数的指针,申明起来比较怪,像这样:


void (*pf)(int) = &foo;

申明一个类型是void (*)(int)的函数指针pf,并初始化为&foo,这里的函数参数类型形式和返回类型要和foo的声明一致。再多一个例子吧:

int foo2(float a,double b)
    {
        return 0;
    }

    int (*pf2)(float,double) = &foo2;


函数指针的使用,两种方式:

(*pf)(100);

即,先引用*,打括号,再传实参调用,或者直接,pf(100)。

函数指针的意义:一个函数可以看成是一个策略,对于一个问题,可以采用不同的策略和方法,这种对策略的选择推迟到运行期,即用一个变量保存起来,在 程序跑起来的时候,决定使用什么策略,其本质即是动多态,对一个函数的调用延迟到运行时决定。

3,指向成员数据的指针

在要说成员指针之前,要先明确一个概念:名称的受限。C++有一套自己的名称查找机制,一个名称可以是一个类名,对象名,函数名等。受限是指是否 用::,->,.中的一种符号作用。

看一般的成员数据访问:


struct A{int a;};

    A a;
    A* p=&a;
    cout<<a.a<<p->a<<endl;


当然类A的定义和下面三条语句不是在一起的,a.a是正确的名称,第一个a没有受限,指对象a,第二个a受限了,是在一个前提下进一步指成员 A::a,这里就是a的成员A::a。再举个例子:


struct A
{
    A(int a)
    {
        this->a=a;
    }
    int a;
};

受限的名称要受前面的名称作用,如果a没有确定,那a.a就不能确定,确定a可以使用指针,当然确定a.a也可以使用指针,即成员指针。题外话,在模板中 如果一个名称被一个包含模板参数的表达式限制,即被一个不确定的东西限制,那它的绑定将延迟到模板的实例化时,如果表示类型,要前加typename,如 果表示成员模板,要在.和->后加template。比如一个模板类(或者叫类模板)中的成员函数中的this指针,实际上它的类型是不确定的, 如:

template
class V
{
};

的this是V*类型的。

转到正题。成员指针实质上是成员数据的偏移。像这样定义:

int A::*p;

它不能直接指向一个数据,因为它必须要是一个受限的名称,它只能指向一个类的成员,它像这样赋值和初始化:

p=&A::a;

它不能单独使用,因为单独使用的时候是非受限的,要先定义一个A的对象,再限制使用:

A a(100);
cout<

它必须放在一个限制式的右边。用几个例子来说明一下:



A a(100);
    A *p1=&a;
    int A::*p2=&A::a;
    cout<<p1->*p2<<endl; //实际访问了a.a


另外一个含内套类的复杂一些的例子:

    struct A
    {
        A(int _a,int _b): a(_a),b(_b)
        {
        }
        struct B
        {
            B(int _b): b(_b)
            {
            }
            int b;
        };
        int a;
        B b;
    };

    int main()
    {
        A a(1,2);
        A *p1=&a;
        A::B A::*p2=&A::b;
        int A::B::*p3=&A::B::b;
        cout<<*p1.*p2.*p3<<endl;
        return 0;
    }


4,指向成员函数的指针

如果(3)弄清楚了这个也应该很明白了,成员函数默认绑定this指针,即成员函数名也是一个受限的名称。它的定义和一般的函数定义类似,只是在指 针前加上一个类名和::。


struct A
    {
        A(int a)
        {
            this->a=a;
        }
        void foo(int)
       {
       }
        int a;
    };

    A a;
    void (A::*pf)(int) = &A::foo;
    (a.*pf)(100);// 相当于调用a.foo(100)


使用和(3)一样,完了再括起来传参调用函数,这个时候不能使用另外一种调用形式了,即不能这样调用:a.pf(100),即使pf是A的成员数据也不可以,例如:

    struct A
    {
        A(): pf(&A::foo1) {}
        A(int): pf(&A::foo2) {}
        void foo1(int)
        {
            cout<<"foo1 is called"<<endl;
        }
        void foo2(int)
        {
            cout<<"foo2 is called"<<endl;
        }
        void foo()
        {
            (this->*pf)(0);
        }
        void (A::*pf)(int);
    };

    int main()
    {
        A a,b(0);
        a.foo();// 输出 foo1 is called

        b.foo();// 输出 foo2 is called

        return 0;
    }


为什么不能默认使用pf呢?pf是A的成员,按理说会有隐含的this->在前面,如果foo()里换成:(*pf)(0);,会编译错误。 原因是,pf是成员,但*pf不是,如果像后者那样调用,它相当于:(*(this->pf))(0)。直接引用了成员指针。

另外,static成员数据和成员函数不能用成员指针,它们不认为是对象的一部分,它们可以直接用一般指针访问,当然它们也是受限的名称,但是受一 个类名限制和对象名无关。

阅读(698) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:最长递增子序列问题的求解(LIS)

给主人留下些什么吧!~~