1.困惑的二级指针
#include <iostream> using namespace std; void pt(int* *t) { cout<<t<<endl<<*t<<endl<<**t<<endl; } int main() { int a = 1; cout<<&a<<endl; int* p = &a; pt(&p); return 0; }
注意pt这个函数,使用的是就是二级指针作为参数:
我们这样理解所有的变量
变量名 | 值 | 地址 |
好了我们的例子:
变量a表示为(我们的地址都是瞎编的):
a | 1 | 11FA |
变量p表示为:
p | 11FA | 10BC |
那么&p如何表示呢?假如我另外设变量int* q = &p;
q(其实就是&p) | 10BC | 1F1B |
这样理解我们的函数pt(int* *p)会打印出什么了吧?
应该依次打印:t *t **t,即为:&p(也就是我们假设的q的值) p a的值,分别为:10BC 11FA 1。
注意几点就好:
1.无论怎么变化,请理解指针变量必须指向地址,就是说,定义了一个指针变量,那么这个指针变量的值一定是个地址,不论这个地址里面对应的值到底是什么东西。
2.不管怎么在变量前面使用修饰符,比如int *p, int **p, 哪怕是int ********p(这个我也搞不懂了),只需记住,我就是定义了一个变量p而已,其它的都是类型,就像我们定义的int p; p是变量,只不过是int型的变量,p的值就只能是int型,同理,int *p;p是变量,只不过这个变量是int*类型的,值就只能是地址。那么int **p,p是变量,只不过是int**类型的,那么p的值就只能是地址在地址的一个值,比如上面例子中变量q,他的值就是10BC这个地址,儿10BC这个地址里面的值有事11FA这个地址。
3.这里pt函数的参数int **p,注意传入的时候,就只能是地址的地址了。
2.const & *说明
请看如下代码(注释掉的代码就是错误的):
#include <iostream> using namespace std; void reffun() { } void poinfun() { } int main() { int a = 1; int b = 2; const int c = 3; int* p1 = &a; p1 = &b; //p1 = &c; const int* p2 = &a; //<==>int const* p2 = &a; //*p2 = 5; p2 = &b; p2 = &c; int* const p3 = &a; //p3 = &b; int &ref1 = a; ref1 = b; ref1 = c; //int &ref2 = 10; const int& ref2 = a; //<==>int const &ref2 = a; //ref2 = b; //ref2 = c; //ref2 = 4; int& const ref3 = a; //<==> int & ref3 = a; ref3 = b; ref3 = c; ref3 = 10; //int &ref4 = 10; const int &ref4 = 10; return 0; }
const与指针:请在*号后画一条竖线,const修饰哪个,那么它的值就不能变。
const与引用:其实引用最开始就是不能const的,即int & const a = b;和int &a = b是等价的。但是const int& a;这个const修饰的是&a,表明&a(这里不是取址符号,是指它本身,不能变。即a是不能改变b的值,但是b的值改变,会反映到a上。就理解为a是一个指向b的常量,int *const a = b ????)
最重要的注意const修饰的引用和指针要对应常量的情况。比如const int &ref = 10;其中10是一个不能变的常量,如果使用int & const ref=10就错了,因为ref的值是可以变的。
3.函数形式参数与引用和指针
其实很好理解,指针传递进来就是地址,我对这个地址的值进行了修改,那么原始变量(地址还是这个地址)的值也会变化
如果是引用,就相当于给原来的地址上配置了两个变量名,修改其中任何一个,都将对这个地址对应的值进行修改。
指针:
变量a | 值为1 | 地址是1A1B |
其中有一个指针变量p指向了a,那么p的值就是1A1B,*p就是1,现在修改*p的值为2,那么
变量a | 值为2 | 地址是1A1B |
如果是引用:
变量a | 值为1 | 地址是1A1B |
有一个引用int &b = a;
变量b | 值为1 | 地址是1A1B |
那么修改a或者b都会影响另外一个的值。
注意下面的调用的影响:
#include <iostream> using namespace std; void my_swap(int* m, int* n) { int x = 3; m = &x; } void my_ref_swap(int& m, int& n) { m = 3; } int main() { int a = 1; int b = 2; my_swap(&a, &b); //my_ref_swap(a, b); cout<<a<<endl; return 0; }
其中my_swap函数里面对指针变量m的指向进行了修改,注意:相当于对m这个形式参数进行修改,并不会对调用函数的a的值有任何影响。
其实按照如下理解就可以了:
my_swap函数int *m = &a, int *n = &b,那么m或者n的指向变化后,是不会对a b的原始值有影响的
my_ref_swap函数int &m = a, int &n = b,a和b已经绑定在了m n上.
4.指针 引用与多台
看代码:
#include <iostream> using namespace std; class A { public: void test1() { cout<<"A:test1()"<<endl; } virtual void test2() { cout<<"A:test2()"<<endl; } }; class B:public A { public: void test1() { cout<<"B:test1()"<<endl; } void test2() { cout<<"B:test2()"<<endl; } }; class C:public B { public: void test1() { cout<<"C:test1()"<<endl; } void test2() { cout<<"C:test2()"<<endl; } }; int main() { A a; B b; A *p = NULL; p = &b; p->test1(); b.test1(); a.test1(); p->test2(); b.test2(); a.test2(); C c; B *d = NULL; d = &c; d->test2(); p = &c; p->test2(); A m; B n; A &refa = n; refa.test2(); return 0; }
一目了然,不用说什么。virtual 基类指针 是多态的核心。