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 基类指针 是多态的核心。