指针小结 学C/C++避不开的这些点

捋了一下这些日子使用指针碰到过的坑,如图:

在这里插入图片描述
可通过右下角目录直接到达相应模块。

一、函数与指针:

这模块分为 指向函数的指针 返回指针的函数

1、指向函数的指针即函数指针):

要定义函数指针,首先得清楚函数的类型
函数的类型由:函数的参数返回类型 来区分。
例子如下:

int Max(double,double);
double*Max(double,double,int);

第一个式子的 函数参数 为两个double,返回类型 为int,
第二个式子的 函数参数 为三个,返回类型 为double*(即指向double型的指针)。

函数的参数 和 返回类型 统称为函数的接口

感觉有点绕,但大体的意思就是 如果函数的接口相同就可以归纳为同一类,如图:
在这里插入图片描述
注意头字母大写是为了与头文件< cmath >中的函数区分。

更具体的例子

//compareNum.h

#include<iostream>
#include<cmath>
using namespace std;
double Max(double a,double b){
	cout<<"两数间最大值:";
	return max(a,b);
}
double Min(double a,double b){
	cout<<"两数间最小值:";
	return min(a,b);
}
double Aver(double a,double b){
	cout<<"两数的平均值:";
	return (a+b)/2;
}

//Main.cpp

#include"compareNum.h"
typedef double Compare(double,double);//注意这里

int main()
{
	double p=2,q=3;
	
	Compare *Com;//此时声明一个指针Com: 返回类型为double, 函数参数为(double,double)。
	
	//double (*Com)(double,double); 也可以像左边这样直接声明,但个人感觉是上面的好用,下面会说到原因。
	
	Com=Max;
	cout<<Com(p,q)<<'\n';
	
	Com=Min;
	cout<<Com(p,q)<<'\n';
	
	Com=Aver;
	cout<<Com(p,q)<<'\n';
	
	return 0;
}

运行结果:
在这里插入图片描述

//用typedef更好用的原因:
typedef double Compare(double,double); Compare *Com;
double (*Com)(double,double);
//假设有下面的函数:
double freeCompare(Compare *Com,double a,double b);
double freeCompare(double(*Com)(double,double),double a,double b);

比较第一和第二个,
老实说,把一推东西塞进 函数参数列表 看得有点头皮发麻。。。
函数指针与普通指针类似,这里最重要是把 函数 抽象成 和(int、double) 是同一类的“东西”。

为什么可以这样抽象的原因:

typedef double Compare(double,double); Compare *Com1;
double *Com2;
sizeof(Com1)==sizeof(Com2)==8;

即在计算机里,都是一块连续的区域。

2、返回指针的函数:

这个部分相对上面的更容易理解,看下例子:

#include<iostream>
#include<cmath>
using namespace std;

double *Max(double a,double b){
	double *p;
	double t=max(a,b);
	p=&t;
	return p;//返回p的地址
}

int main()
{
	double *u=Max(3,5);//u指向 Max(3,5) 传回来的p的地址
	cout<<*u;
	return 0;
}	

运行结果是5。
这个部分在数据结构中比较常用,比如 排序后返回头节点 或者是 关于树的操作返回根节点。

二、数组与指针:

这模块分为 指针数组 数组指针
这两个的区分主要看后缀
前一个是一个数组,后一个是一个指针。

1、指针数组

数组里的元素全部都是指针的 数组,如下:

#include<iostream>
using namespace std;


int main()
{
	int *pi[3];
	int a=11,b=22,c=33;
	
	pi[0]=&a;
	pi[1]=&b;
	pi[2]=&c;
	
	for(int i=0;i<3;i++){//输出数组里的指针 指向的数据
		cout<<*pi[i]<<' ';
	}
	cout<<endl;
	
	for(int i=0;i<3;i++){//输出数组里的 指针(即数据的地址)
		cout<<pi[i]<<' ';
	}
	cout<<endl;
	
	for(int i=0;i<3;i++){//输出数组的 地址(即存放指针的地址)
		cout<<&pi[i]<<' ';
	}
	return 0;
}

运行结果:
在这里插入图片描述
有没有发现规律?
中间的三个地址之间相差4字节(对应a、b、c),
最下面的三个地址之间相差8字节(对应指针数组)。

2、数组指针

指向数组的指针,例子如下:

#include<iostream>
using namespace std;
int main()
{
	int a[3]={4,5,6};
	int *p=a;
	
	for(int i=0;i<3;i++){
		cout<<a[i]<<' '<<&a[i];//用数组输出 数据和地址
		cout<<*(p+i)<<' '<<(p+i)<<'\t';//用指针输出 数据和地址
		cout<<endl;
	}
	return 0;
 } 

运行结果:
在这里插入图片描述

三、类与指针:

这模块要说的是 基类指针与虚函数 this指针

1、基类指针与虚函数

这部分常用的是 基类指针 指向 派生类对象 从而实现多态性,例子如下:

//A.h

#include<iostream>
using namespace std;
class A{
	public:
		virtual out(){
			cout<<"A:你好,多态性"<<endl;
		}
		out1(){
			cout<<"A:你好,非多态性"<<endl;
		}
};

class B:public A{
	public:
	out(){
		cout<<"B:你好,多态性"<<endl; 
	}
	out1(){
		cout<<"A:你好,非多态性"<<endl;
	}
};

class C:public A{
	public:
		out(){
			cout<<"C:你好,多态性"<<endl;
		}
		out1(){
			cout<<"A:你好,非多态性"<<endl;
		}
};

//Main.cpp

#include"A.h" 
int main()
{
	
	A u0;
	B u1;
	C u2;
	
	A *p=&u0;
	p->out();
	p->out1();
	cout<<endl;
	
	p=&u1;
	p->out();
	p->out1();
	((B*)p)->out1();
	cout<<endl;
	
	p=&u2;
	p->out();
	p->out1();
	((C*)p)->out1();
	return 0;
 } 

运行结果:
在这里插入图片描述
截图在同一面中可能更直观一些。

基类指针 指向 派生类对象 与 virtual 联用能实现多态,
但是如果不与 virtual 联用则只能调用基类成员;

使用 基类指针 指向 派生类对象 的原因:可以实现 异质链表 从而用一个基类的头节点管理 各个不同的派生类对象。

2、this指针

//p.h

#include<iostream>
using namespace std;
class p{
	public:
		void out1(){
			cout<<x<<' '<<y<<endl;
		}
		void out2(){
			cout<<this->x<<' '<<this->y<<endl;
		}
		
	private:
	int x=2,y=3;
};
//Main.cpp
#include"p.h"

int main()
{
	p u;
	u.out1();
	u.out2();
	return 0;
}	

this指针需要注意的点是 不能显式说明,但可以在成员函数中直接显式使用
this指针初始化后 不能 修改和赋值。

以上的内容都是咱使用过并且认为相对重要的点,如果想看更多详细内容请翻回手上的 教材

如果对你有用 或者 让你想起了某些已经遗忘的知识 ,
顺手给我来波三连哇。
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值