指针
【1】如何理解指针?
指针,就是地址值。强调一点,计算机世界就是对现实的一种精确模拟。那么,既然是模拟,现实中什么是指针呢?嗯,对了,大概你已经想到
了,就是可以等价于你家的门牌号。如果你是一个学生的话,那就是你的座位号;如果你刚买了一座别野(别墅的雅称,其实这个名字更有意义,因
为如果人人都住别墅去了的话,人与人之间就没有那么多的沟通,也就相当于野人了,所以叫“别野”),那么指针就是你家的别野号。
由于现实的地址也是多种多样的,所以在计算机世界里,指针也是很多类别的。
【2】各种指针有何特性?
(1)一般指针
示例代码以及相关分析如下:
1 #include<iostream> 2 using namespace std; 3 4 void main() 5 { 6 int a = 10; //定义int型变量a并赋值为10 7 cout<<"&a="<<&a<<endl; //输出变量a的地址 8 int *p = NULL; //定义指针变量p.此指针变量的类型为int *.也就是指向整型变量的指针。由于暂时不确定指向,赋值空NULL 9 int *pa = NULL,b; //这种写法必须要注意:“*”符号只对pa有效,也就是说pa才是指针变量。b是一个整型变量。 10 pa = &a; //pa这个指针变量指向了a这个整型变量。注意这里有一个类型匹配的问题。即就是:赋值兼容性原则。 11 cout<<"pa="<<pa<<endl; 12 b = 20; 13 *pa = b; 14 //pa的内容就是pa这个指针变量的另外一个值,此句主要是为解释指针的双值性。执行这一句,*pa原来的内容就会变为b变量的值,即就是20。这就是运行结果a=20的依据。 15 cout<<"pa="<<pa<<endl; 16 cout<<"a="<<a<<endl; 17 } 18 //The result of this 19 /* 20 &a=0x0012FF7C 21 pa=0x0012FF7C 22 pa=0x0012FF7C 23 a=20 24 */
(2)函数指针
<1>可以把一个指针声明为一个指向函数的指针。示例代码如下:
1 int fun1(char *,int); 2 int (*pfun1)(char *,int); 3 pfun1 = fun1;
声明函数fun1。再声明函数fun1的指针pfun1。注意观察指针的类型以及指针指向的类型。
再给函数指针赋值。注意这里也是必须要遵守赋值兼容原则。
<2>通过函数指针调用函数的两种形式过程说明。示例代码如下:
1 #include<iostream.h> 2 int add(int a,int b) 3 { 4 return a+b; 5 } 6 int max(int a,int b) 7 { 8 return a>b? a:b; 9 } 10 void main() 11 { 12 int (*fun)(int,int); //函数指针 fun为类型名 13 fun=add; 14 cout<<fun(12,23)<<endl; 15 fun=max; 16 cout<<(*fun)(23,34)<<endl; 17 } 18 /* 19 运行结果: 20 35 21 34 22 */
过程说明:
第十二行:一个函数指针,fun为函数指针变量名。
第十三行:赋值为add函数
第十四行:调用函数fun()。通过指针实现如上所示。
第十五行:赋值为max函数
第十六行:调用函数max()。通过指针实现如上所示。
(3)this指针
面向对象编程的关键是类的设计,而类设计的难处主要在于它是很抽象的,抽象怎么解释呢?
举个生活中的例子。比如说:“XXX,你去给我买两斤水果,回来再给你还钱。”好了,这就是个很具体的例子。
那么,这个水果到底指的是什么东东?是苹果?是梨?是橘子?是......总之,这个概念太抽象了。
但是,水果还真是一个类别,你看大街上什么餐饮店,什么水果超市,什么鞋店。什么书店等等的。
嗯,高度抽象都是有一种共同行为的东西!这就是所有面向对象程序设计书中提到的那个行为的概念。
而所谓的属性是指本身的相关特性。好,既然同一个类中所衍生的对象都是具有相同行为的,只不过属性彼此不同而已。
为了节省空间,方法也就是所谓的成员函数在内存中也就只有一份拷贝。
那么,这也就存在一个问题,各个对象公用一份拷贝的成员函数,到底是哪个对象调用成员函数?就取决于对象的this指针。
其实,在每个成员函数【除过静态的】的参数部分,都有一个隐藏的this指针,而且它是这样子定义的:class * const this
示例代码如下:
1 #include<iostream.h> 2 class Test 3 { 4 private: 5 int value; 6 public: 7 Test(int x=0):value(x) 8 {} 9 ~Test() 10 {} 11 void fun() 12 { // void fun(Test * const this) 13 cout<<this->value<<endl; 14 } 15 }; 16 17 void main() 18 { 19 Test t1(10),t2(100); 20 t1.fun(); 21 // fun(&t1);本质上应该是这样的过程 22 t2.fun(); 23 // fun(&t2);本质上应该是这样的过程 24 } 25 //The result of this 26 /* 27 10 28 100 29 */
【3】关于指针的以下应用分析:
从变量名处起,根据运算符优先级结合,一步一步分析
1 int p; //这是一个普通的整型变量 2 3 int *p; //首先从P 处开始,先与*结合,所以说明P 是一个指针,然后再与int 结合,说明指针所指向的内容的类型为int 型.所以P是一个返回整型数据的指针 4 5 int p[3]; //首先从P 处开始,先与[]结合,说明P 是一个数组,然后与int 结合,说明数组里的元素是整型的,所以P 是一个由整型数据组成的数组 6 7 int *p[3]; //首先从P 处开始,先与[]结合,因为其优先级比*高,所以P是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与int 结合,说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型数据的指针所组成的数组 8 9 int (*p)[3]; //首先从P 处开始,先与*结合,说明P 是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P 是一个指向由整型数据组成的数组的指针 10 11 int **p; //首先从P 开始,先与*结合,说是P 是一个指针,然后再与*结合,说明指针所指向的元素是指针,然后再与int 结合,说明该指针所指向的元素是整型数据.由于二级指针以及更高级的指针极少用在复杂的类型中,所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针. 12 13 int p(int); //从P 处起,先与()结合,说明P是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数然后再与外面的int 结合,说明函数的返回值是一个整型数据 14 15 int (*p)(int); //从P处开始,先与指针结合,说明P 是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P是一个指向有一个整型参数且返回类型为整型的函数的指针 16 17 int *(*p(int))[3]; //可以先跳过,不看这个类型,过于复杂 18 //从P 开始,先与()结合,说明P 是一个函数,然后进 19 //入()里面,与int 结合,说明函数有一个整型变量 20 //参数,然后再与外面的*结合,说明函数返回的是 21 //一个指针,,然后到最外面一层,先与[]结合,说明 22 //返回的指针指向的是一个数组,然后再与*结合,说 23 //明数组里的元素是指针,然后再与int 结合,说明指 24 //针指向的内容是整型数据.所以P 是一个参数为一个 25 //整数据且返回一个指向由整型指针变量组成的数组 26 //的指针变量的函数.
备注:2012-12-31