C++ 面向过程基础

2024-01-03

一、指针数组

  • 数组元素是指针的数组是指针数组,

  • // 语法规范: 类型名 * 数组名【数组长度】

	int arr[2][3] =
	{
		{10,20,30},
		{40,50,60}
	};
	int* p[2];
	p[0] = arr[0];
	p[1] = arr[1];
	for (int i = 0; i < 2; i++) 
	{
		for (int j = 0; j < 3; j++)
		{
			cout << *(p[i]+j)<<" ";
		}
		cout << endl;
	}

二、多级指针

  • 如果一个指针变量保存的是另外一个指针变量的地址,我们称之为多级指针,或者纸箱指针的指针

    • p1, ** p2;

    •  *int a, * p1, ** p2;
       	p1 = &a;
       	p2 = &p1;
       	**p2 = 100;
       	cout << "&a=" << &a <<"\tp1=" << p1 << "\tp2=" << p2 << endl;
       	cout << "a=" << a << "\t*p1=" << *p1 << "\t**p2=" << **p2 << endl;*/
       
      

    //二维数组地址问题

      ```
      int arr[2][3] =
      		{
      			{10,20,30},
      		{40,50,60}
      		};
      // arr+1 arr[1]和arr[1][0]都是第二行的首地址
      cout << arr+1 <<"\t" << arr[1] << "\t" << &arr[1][0] << endl;
      //  **arr 等于 *arr[0]
      
      for (int i = 0; i < 2; i++) 
      {
      	for (int j = 0; j < 3; j++) 
      	{
      		cout << *(*(arr+i)+j)<<endl;
      	}
      	
      }
      for (int i = 0; i < 6; i++) 
      {
      	cout << *(*arr+i) << endl;
      }
      
      ```
    

三、数组指针

​ * 语法规范: 数据类型(*指针变量名)[长度]

int(*p)[5];// 定义一个数组指针,可以指向一个具有五个int类型的元素的数组
int arr[5] = { 10,20,30,40,50 };
// 使用&arr为p进行赋值,而不能使用arr对p进行赋值
cout << arr << "\t" << &arr << endl;
//虽然arr和&arr的地址是一样的,但是含义不同,arr代表的数组第一个元素的首地址,&arr才是整个数组的地址
p = &arr;
for (int i = 0; i < 5; i++) 
{
	cout << (*p)[i]<<"\t";
}
  • 指针数组和数组指针的总结:
    从概念上进行区分:
    指针数组本质上是一个数组,数组里面元素是指针;
    数组指针本质上是一个指针,是要指向整个数组;
    从运算符的优先级上进行区分:
    指针数组:
    int p[10]; 因为[]的优先级比的优先级高,所以是先有数组,然后才有int类型的指针变量的数组元素
    数组指针:

    int (*p)[10]; 因为()的优先级更高,所以是先获取指针,然后再让这个指针指向整个数组。

四、指针常量和常量指针

  • 常量指针:指针指向的内存地址中的内容不是不可以的修改的

    const 数据类型 * 指针名=地址;
    int a = 10, b = 20;
    const int* p = &a;
    //p = &b;
    // 常量指针的指向内容不可以修改
    *p = 100;
    cout << *p << endl;

  • 指针常量:指针的指向不可以修改,但是指向的内存中的只可以修改

    int * const p= 地址
    int a = 10, b = 20;
    int * const p = &a;
    // 指针常量的指向不可以修改
    //p = &b;
    *p = 100;
    cout << *p << endl;

	char ch[] = "dasfa";
	int arr[] = { 1,2,3,4 };
	char* p = ch;// p=&ch
	int* q = arr;// q=&arr
	for (int i = 0; i < strlen(ch); i++)
	{
		cout << *(p + i);
	}
	for (int i = 0; i < 4; i++)
	{
		cout << *(q + i);
	}

五、动态内存分配

  • 程序在运行的时候可以使用malloc和new来进行内存的申请,程序员要自己负责使用free或delete来释放内存

    // new来进行内存分配
    // 语法:单个内存分配 new 类型名(初始值); 多个内存空间的分配:new 类型名[整型表达式];
    // 释放内存:释放单个内存 delete 指针名; 多个内存释放 delete[] 指针名;


// 分配单个内存
int* p1 = new int(10);
cout << *p1 << endl;
// 分配多个内存空间,分配连续的10个int类型的内存单元
int* p2 = new int[10];

// 释放单个内存空间
delete p1;
// 释放多个内存空间
delete[] p2;
// 释放完成之后,将其置为空指针,会避免野指针的报错(p = NULL);
	p2=NULL;

六、引用

  • 引用的概念:引用是对已有变量或者表达式的一种别名机制,主要用在函数的形参和返回值
  • 作用:给变量起别名
  • 语法:数据类型&别名=原名;
  • 本质是一个指针常量(里面的内容不能改变) int *const p=&a
  • 引用的注意事项:
    1、引用必须要进行初始化
    2、引用初始化后不可改变

```
	int a = 10,c=20;
	int& b = a;
	cout << a << "\t" << b << endl;
	b = 100;
	/*
	b初始化不能不能作为其他变量名命名
	b = c;
	*/
	cout << a << "\t" << b << endl;

	// 本质是一个指针常量(里面的内容不能改变)   int *const p=&a;
	int* const p = &a;
	int& ref = a;
```

七、参数的使用

1.函数的基本使用:

  • 函数的概念:在程序设计的时候,如果一段代码重复进行某个操作或者完成某 - 项功能,这样的代码组织就叫做函数

    //函数的定义 : 函数类型函数名(形参) { 函数体 };
    //函数的调用:函数名(实参);
    //函数类型和返回值:
    //函数可以有返回值也可以没有
    //函数的类型就是函数返回值的类型,可以是任何一种类型
    //函数的返回值由函数体中的return语句给出
    //如果函数没有返回值,函数的类型void来定义
    //函数参数 :
    //形参(形式参数) : 定义函数的时候括号中写的参数
    //实参(实际参数) : 调用函数的时候括号中写的参数

2、参数问题

  • 地址传递

    // 指针作为函数的形参
    // 指针作为函数的参数的时候会改变实参的值,
    // 因为形参的指针变量和实参指的是同一块内存空间,所以对于指针变量的操作,实际上就是对于实参的操作。
    // 引用作为函数的形参会影响实参的值
    // 因为引用是一种别名机制,对于引用形参的操作实际上就是对于实参的操做
    引用参数和数值参数的比较:
    //引用作为函数的参数的时候,调用的时候的实参只能是变量,如果数值作为函数的形参,那么实参可以是变量、也可以是常量或者表达式。
    // 引用传递,实参只能是变量
    // 数组作为函数的参数的时候实际上传递的是数组的首地址
    // 字符指针作为函数的参数,接受的是字符数组的首地址

八、全局变量

  • 变量的生命周期

    // 每一个标识符都有自己的特定的作用范围,也就是自己的生命周期,如果超过这个范围就会被自动销毁。

​ 全局变量:在函数的外部进行定义的变量,会在函数的范围外和范围内都能使用。
​ 局部变量:函数中定义的变量,只能在当前的函数里使用,如果超过函数的范围就会失效。

九、函数的存储类别

静态存储和动态存储

  • 动态变量 数据类型 * 数据名= new int();

  • 静态变量 static 数据类型 数据名

  • 静态变量只初始化一次

十、内联函数和重载函数

  • 内联函数通常用于小而简单的函数,以减少函数调用的开销,提高程序的执行效率。
内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展)
// 声明内联函数
inline int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(3, 4);  // 函数调用被编译器替换为表达式 3 + 4
    std::cout << "Result: " << result << std::endl;
    return 0;
}

  • 重载函数:C++中可以定义同名参数,只要他们的形参 类型或者个数不同
int getMin(int a, int b,int c)
{

return a < b ? (a<c?a:c) :( b<c?b:c);
}

int getMin(int a, int b)
{
	return a < b ? a : b;
}

十一、函数的默认参数:

在定义函数的时候,可以预先给函数的形参来指定默认值,
在函数调用的时候如果传递了实参就使用实参,如果没传递就用形参的默认值即可
默认的形参的默认值的顺序必须要从右向左进行定义,如果某个形参有默认值,那么它右边的所有形参必须都有默认

int getSum(int x, int n=2) 
{
	int k = 1;
	for (int i = 0; i < n; i++)
	{
		k  *= x;
	}
	return k;
}

十二、函数指针的使用:

  • 我们需要定义可以直接保存函数指针变量来保存

  • 语法规范: 函数类型(函数指针名)(参数类型列表)

    */
    //定义函数指针变量
    int (*fp)(int, int,int);

  • 函数的嵌套调用:

    //在C + +中函数的定义都是相互独立的,不允许在一个函数中定 义另外一个函数,
    //但是允许在一个函数中调用另外一个函数。

  int fun02(int x)
  {
  	int c = 1;
  	for (int i = 1; i <= x; i++)
  	{
  		c = c * i;
  	}
  	return c;
  }
  int fun01(int n) 
  {
  	int s = 0;
  	for (int i = 1; i <= n; i++)
  	{
  		s = s + fun02(i);
  	}
  	return s;
  }

十三、结构体:

  • 结构体:

    struct 结构名
    {
    数据类型1:成员名;
    数据类型2: 成员名2
    }

    */

    * //定义结构体来储存学生信息
    	//struct score 
    	//{
    	//	double Chinese;
    	//	double Math;
    	//
    	//};
    
    	 typedef struct student 
    	{
    		int Id;
    		string Name;
    		double score;
    
    	}Stu;
    	 /*
    
    	 * 结构体名称
    	 * 1.typedef struct student stu;
    	 * 2 后面 stu;
    	 * 3.student stu;
    	 * 结构体指针 
    		*/
    		struct dog* p
    		{
    
    	 };
    	 double  aver(Stu* p) 
    	 {
    		 double sum = 0;
    		 for (int i = 0; i < 5; i++)
    		 {
    			cout << "Id=" << p[i].Id << "\tName=" << p[i].Name << "\tscore=" << p[i].score << endl;
    			 sum += (p+i)->score;
    		 }
    		 return sum/ 5;
    	 }
    
    /*
    

十四、联合:

有时候需要使用几个不同的变量占用同一块内存空间,就可以定义一 个联合来实现,联合也叫做共用体。

语法: union联合名{数据类型1成员名1;数据类型2成员名..};

联合体中的所有成员变量共用一块内存空间,如果对一个成员的值进行修改,那么也会同时影响其他的成员的值。
因为联合体中的所有成员都是占用同一块空间的,所以联合体的大小就是所有成员中占用最大内存的成员的大小。

*/
union myData 
{
	int i;
	char ch;
}md;

/*

十五、枚举

  • 枚举是用标识符来表示整型常量的集合,使用enum来定义
  • 枚举类型语法: enum 枚举类型名{枚举类型1,枚举类型…];.
  • 枚举类型中元素的起始值如果不指定,将自动从0开始为各个枚举元素进行初值的赋值,后面枚举元素依次加1
enum weekday {Sun=7,Mon=1,Tue,Wed,Thu,Fri,Sat};

十六、命名空间

  • 如果大型程序需要程序员来进行维护,为了避免出现标识符冲突问题

  • 注意:

  • 命名空间只可以在全局范围进行定义,但是可以嵌套

  • 定义一个命名空间实际上就是定义-个域,命名空间中的所有内容都局限于该空间中。命名空间的定义

    只影响使用,不影响生命周期。定义命名空间需要使用namespace 关键字。后跟空间名字,然后接一对
    {}即可, {}中即为命名空间中的成员。

```
namespace NameSpace1
{
	int a = 10;
	void fun(int x,int y)
	{
		cout << "namespace1函数" << endl;
		cout << x*y << endl;
	}
}
namespace NameSpace2
{
	int fun(int x, int y);
	namespace ns3
	{
		int fun(int x, int y);

	}
	
}

namespace ns1 = NameSpace1;
namespace ns2 = NameSpace2;

int ns2::fun(int x, int y)
{
	return x - y;
}
int ns2::ns3::fun(int x, int y)
{
	return x + y;
}
int main()
{
	
	cout << ns2::fun(10, 20) << endl;
	cout << ns2::ns3::fun(10, 20);

	return 0;
}
```

十七、文件分层处理

  • 头文件:一般存放的是结构体的定义、函数的原型(声明)、全局常量,还有类等等。
  • 源文件:存放的是函数的定义,还有其他的一些功能等。
多文件实现的案例:
编写一个处理平面图形的程序
设计一个表示图形中心点的结构体Point,有两个int类型的成员来表示点的坐标
设计一个表示圆的结构体Circle,包含个Point成员表示圆心, 还有一个double成员表示半径
设计一个表示矩形的结构体Rectangle,包含一个Point成员矩形的图形中心, 还有两个double类型的成员表示矩形的长和宽。
要求:能够计算两个图形的面积和周长。

Point.h: Point结构体的定义
Circleh: Circle结构体的定 义以及与Circle相关的函数原型(声明)
Rectangle.h: Rectangle结构体的定义以及与Rectangle相关的函数原型(声明)
Circle.cpp:与Circle相关的函数定义
Rectangle.cpp:与Rectangle相关的函数定义
Main.cpp:主函数所在的文件

Main()函数

#include<iostream>
#include"Circle.h"
#include"Rectangle.h"
using namespace std;


int main()
{
	struct Circle c = { {10,20},10 };
	cout <<"圆的面积:" << sC(c) << endl;
	cout << "圆的周长:" << cC(c) << endl;

	struct Rectangle re = { {10,20},10 ,20};
	cout << "矩形的面积:" << sJ(re) << endl;
	cout << "矩形的周长:" << cJ(re) << endl;
	return 0;
}

头文件:

//#pragma once

#ifndef Point_H

#define Point_H
struct Point
{
	int x;
	int y;

};
#endif


#pragma once
#include "Point.h"
struct Circle
{
	Point point;
	double r;  //半径
};


double sC(struct Circle);


double cC(struct Circle);

源文件

#include"Circle.h"

double sC(struct Circle c)
{
	double π = 3.14;
	return π * c.r *c.r;
}
double cC(struct Circle c)
{
	double π = 3.14;
	return π * c.r * 2;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值