C++Day3

复习:
什么是引用?
别名

引用可以改变指向?
定义初始化 不可以改变指向

常引用怎么初始化
    int a;
    const int &ref= a 
                  =100
                  =a+2
引用应用
    形参
    返回值
    
常引用做形参作用
  保护实参不被修改

一、指针
回顾:
内存:
变量索引方式:
1.变量名
2.地址
定义指针
int*p
int *p;
int * p;

*p 

*功能:
1.定义 --前边有类型 
2.取值--前边没有类型

无类型指针---引用前 必须把它转为一种适当的数据类型
void *p;

新知识:
1.变量可能存在的空间:
1)堆:malloc-free new-delete
2)栈:作用域函数调用开始 变量释放作用域结束 int a int arr[3]
3)静态 与程序一样长生命周期

2.动态空间的申请和释放

	c中       函数    malloc-free  #include<cstdlib>     malloc申请的内存空间是没有类型的void*   不会初始化 

	c++中    关键字     new-delete 			                new申请的内存空间是有类型的         给内存初始化

3.动态空间的使用
c++类型检查更严格
#include
#include
using namespace std;

int main()
{
    int *p=(int*)malloc(4);//错误 必须强转

    }	

实例:
#include<iostream>//input output stream  输入输出头文件
#include<cstdlib>
using namespace std;
int main()
{
    int *p = NULL;
    p =(int*)malloc(sizeof(int));
    if(NULL==p)
    {
        cout<<"malloc failed"<<endl;
        return 0;
    }

    *p=100;
    cout<<*p<<endl;

    if(p!=NULL)
    {
        free(p);
        p = NULL;
    }
}

1.变量申请动态空间	
	例1:
    #include<iostream>//input output stream  输入输出头文件
    using namespace std;
    int main()
    {
        int *p=NULL;

        //申请
        p = new int;//申请一块整形空间 返回空间首地址 
        if(NULL==p)
        {
            cout<<"malloc error"<<endl;
            return 0;
        }

        //使用
        *p=666;
        cout<<*p<<endl;

        //释放
        delete p;
        p = NULL;//避免非法使用
    }
    
    例2:
    #include<iostream>//input output stream  输入输出头文件
    using namespace std;
    int main()
    {
        int *p=NULL;

        //申请空间并初始化
        p = new int(666);//申请一块整型空间 并将666赋值进去  返回空间首地址 
        if(NULL==p)
        {
            cout<<"malloc error"<<endl;
            return 0;
        }

        cout<<*p<<endl;

        //释放
        delete p;
        p = NULL;//避免非法使用
    }

练习:在main函数中动态开辟一个整型空间,并初始化为10,再赋值为20,最后注意内存的释放。
#include//input output stream 输入输出头文件
using namespace std;
int main()
{
int *p=NULL;

//申请空间并初始化
p = new int(10);//申请一块整形空间 并将666赋值进去  返回空间首地址 
if(NULL==p)
{
	cout<<"malloc error"<<endl;
	return 0;
}

*p = 20;
cout<<*p<<endl;

//释放
delete p;
p = NULL;//避免非法使用

}

2.数组动态申请空间 
例3:
#include<iostream>//input output stream  输入输出头文件
using namespace std;
int main()
{
    int i;
    int *p=NULL;

    //申请
    p=new int[3];//申请3块连续的整型空间 返回空间首地址  | | | |
    if(NULL==p)
    {
        cout<<"malloc error"<<endl;
        return 0;
    }

    //使用
    for(i=0;i<3;i++)
    {
        p[i] = i+1;
    }

    for(i=0;i<3;i++)
    {
        cout<<p[i]<<"   ";
    }

    //释放
    delete []p;//释放连续空间
    p = NULL;
}
        
    

3.动态空间初始化
例4:
#include<iostream>//input output stream  输入输出头文件
using namespace std;
int main()
{
    int i;
    int *p=NULL;

    //申请
    p=new int[3]();//申请3块连续的整型空间 将数组初始化为0 返回空间首地址  | | | |
    if(NULL==p)
    {
        cout<<"malloc error"<<endl;
        return 0;
    }

    //使用
    for(i=0;i<3;i++)
    {
        p[i] = i+1;
    }

    for(i=0;i<3;i++)
    {
        cout<<p[i]<<"   ";
    }

    //释放
    delete []p;//释放连续空间
    p = NULL;
}


练习:从键盘输入学生分数(int) 统计出最高分 最低分 平均分 要求:动态开辟空间
#include<iostream>
#include<cstdlib>

using namespace std;

int main()
{
    //申请空间
    int* arr = new int[4];
    if(NULL==arr)
    {
        cout<<"申请空间失败"<<endl;
        exit(-1);
    }

    //赋值
    for(int i = 0;i < 4;i++)
    {
        cin>>arr[i];
    }
    
    int max = arr[0];//记录数组中最大值
    int min = arr[0];//记录数组中最小值
    int sum = arr[0];//j记录数组中数据综合
    
    for(int i = 1;i < 4;i++)
    {
        sum += arr[i];
        
        if(arr[i] > max)
        {
            max = arr[i];//最大值更新
        }
        else if(arr[i]< min)
        {
            min = arr[i];//最小值更新
        }
    }

    cout<<"max:"<<max<<" min:"<<min<<endl;
    cout<<"avg:"<<sum/4<<endl;
   
   
      delete []arr;
      arr = NULL;
   
}

4.成员指针
#include
using namespace std;
struct date
{
int year;
int month;
int day;
};

int main()
{
	date d={2022,3,15};

	int date::*mp;//mp是成员指针
	mp=&date::year;
    //int date::*mp=&date::year

	cout<<d.*mp<<endl;//d.year	

	date d2={2018,5,1};
	cout<<d2.*mp<<endl;//d2.year
}  

二、c++对c函数扩展

1、函数重载
理解:不同参数 相同用途
print(char)
print(int)

(1)含义:编程时 一个函数实现一个功能 有时要实现同一类函数的功能 只是细节不同
c++允许创建多个同名的函数(同一函数名 定义多个函数)–一物多用

(2)函数重载要求:形参列表必须不同(形参的类型不同或者形参的个数不同)
返回值无所谓
注意:如果形参列表相同 但返回值不同 是不可以重载

实例1:形参类型不同
#include<iostream>//input output stream  输入输出头文件
using namespace std;

void print(int a)
{
    cout<<a<<endl;
}
void print(char a)
{
    cout<<a<<endl;
}
int main()
{
    int a=100;
    char ch='x';
    print(a);
    print(ch);
}


实例2:形参个数不同
#include<iostream>//input output stream  输入输出头文件
using namespace std;

void print(int a,int b)
{
    cout<<a<<endl;
    cout<<b<<endl;
}
void print(int a)
{
    cout<<a<<endl;
}
int main()
{
    int a=100;
    int d=123;

    print(a,d);
    print(a);
}

练习:函数重载实现求两个数据的和 数据可以都是int类型 也可以都是double类型
#include//input output stream 输入输出头文件
using namespace std;

void my_add(int a,int b)
{
cout<<(a+b)<<endl;
}

void my_add(double x,double y)
{
cout<<(x+y)<<endl;
}
int main()
{
int a=90,b=23;
double x=1.23,y=5.67;
my_add(a,b);
my_add(x,y);
}

总结:
1.重载规则:形参列表必须不同(不能因为函数不同的返回值进行重载)
2. 不提倡太多

注意说明:
关于函数重载,供参考:
1、C++对于字面值常数的默认类型规定
如 3.14默认为double 类型

	 那么,定义如下两个函数,
	 int fun(int n,int m);
	 float fun(float n,float m);
	 
	 fun(10.0,2.5)就有歧义了    ---->解决:fun(10.0f,2.5f) 
	
	2、了解:
		1)形参是引用、非引用时:
		void func(int &x); 
		void func(int x);不属于重载

		示例:
		#include<iostream>
		using namespace std;

		void fun(int &num)
		{
			cout<<"num&..."<<num<<endl;
		}
		void fun(int num)
		{
			cout<<"int ..."<<num<<endl;
		}

		int main()
		{
			int num = 6;

			fun(5);//可以调用整形的函数

			fun(num);//编译报错 发生歧义
	
		}

	2)形参是 const 引用、非const 引用时:
	void func(const int &x);
	 void func(int &x);属于重载。
	 
	3)形参是普通指针、指向常量的指针时:
	void func(int * p) ;
	void func(int const * p);属于重载。 


	4)形参是常指针、指向常量的指针时:
	void func(int const *p); 
	void func(int *const p);属于重载。

	5)形参是普通指针、指向常量的常指针时:
	void func(int * p); 
	void func(int const * const p);属于重载。

	6)形参使用了 typedef、没使用了 typedef时:
	typedef unsigned int UINT
	void func(UINT b); 
	void func(unsigned int x);不属于重载。

2、函数默认值
默认参数:函数调用时 形参可以给一个默认值 这时就不必从实参取值

实例1:如果实参传递值 则使用实参值 实参不传递值 则使用函数默认值
#include<iostream>//input output stream  输入输出头文件
#include<string>
using namespace std;

void set_color(string color="black")//型参默认值
{
    cout<<color<<endl;
}
int main()
{
    set_color();//如果实参不传递值 则使用函数默认值
    set_color("red");//如果实参传递值 则使用实参值
}

实例2:形参默认值必须从右侧开始给
#include<iostream>//input output stream  输入输出头文件
#include<string>
using namespace std;

void set_color(int count,string color=“read”)//错 形参默认值必须从右侧开始给
{
    cout<<count<<endl;
    cout<<color<<endl;
}
int main()
{
    set_color(8,"red");//如果实参传递值 则使用实参值
}


实例3:如果有函数声明 默认参数值要写到声明中
#include<iostream>//input output stream  输入输出头文件
using namespace std;
void  add(int x=1,int y=2);//声明

int main()
{
    //add(10,20);
    add();
}

void add(int a,int b)
{
    cout<<(a+b)<<endl;
}

练习:判断一个年份是否是闰年,声明中给默认年份 
2016
	 year %4 == 0 && year %100 != 0 || year % 400 == 0
   
#include<iostream>//input output stream  输入输出头文件
using namespace std;

//函数声明
void judge(int year=2016);
int main()
{
    judge();
    judge(2022);
}

void judge(int year)
{
    if(year%4==0&&year%100!=0||year%400==0)
    {
        cout<<"润年"<<endl;
    }
    else 
    {
        cout<<"平年"<<endl;
    }
}    

3.内联函数

(1).定义 inline+函数名
(2).c++编译器会直接将内联函数函数体插入到函数调用的位置 所以内联函数没有普通函数跳转的额外开销(压栈,跳转,返回)
例子:
#include//input output stream 输入输出头文件
using namespace std;

inline void add(int m,int n)
{
    cout<<(m+n)<<endl;
}
int main()
{
    add(2,6);//函数调用
    cout<<"end"<<endl;
}

(3).注意:
1)C++编译器不一定准许函数的内联请求!
内联函数是一种特殊的函数,具有普通函数的特征(参数检查,返回类型等)
内联函数是对编译器的一种请求,因此编译器可能拒绝这种请求
2)现代C++编译器能够进行编译优化,因此一些函数即使没有inline声明,也可能被编译器内联编译

(4).C++中内联编译的限制:
不能存在任何形式的循环语句
不能存在过多的条件判断语句
函数体不能过于庞大
不能对函数进行取址操作
函数内联声明必须在调用语句之前
编译器对于内联函数的限制并不是绝对的,内联函数相对于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销。
因此,当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将无意义。

(5)带参宏与内联函数区别
1)带参宏
#include//input output stream 输入输出头文件
using namespace std;

#define MAX(a,b) (a)>(b)?(a):(b)
int main()
{
cout<<(MAX(3,7))<<endl;
}

2)区别
实例:带参宏实现
#include//input output stream 输入输出头文件
using namespace std;

#define MIN(a,b) (a)<(b)?(a):(b)
//(++a)<(b)?(++a):(b)
int main()
{
int a=1;
int b=3;
cout<<(MIN(++a,b))<<endl;//1. 3

cout<<"a:"<<a<<endl;//2. 3
cout<<"b:"<<b<<endl;//3.  3

}

实例:内联函数实现
#include//input output stream 输入输出头文件
using namespace std;

//#define MIN(a,b) (a)<(b)?(a):(b)
//(++a)<(b)?(++a):(b)

inline int min(int m,int n)//m 2 n 3
{
return m<n?m:n;
}
int main()
{
int a=1;
int b=3;
cout<<min(++a,b)<<endl;//1.2

cout<<"a:"<<a<<endl;//2. 2
cout<<"b:"<<b<<endl;//3.  

}

三、面向对象
1、结构体
struct stu
{
int id;
char gender;
char name[20]

void sleep()
{
    "呼呼";
    “~~”
}
void eat()
{}
void class()
{
    
}

}

2、类
介绍对象
面向对象是c++核心
类–模型 对象是具体化的实例

编写对象的模型
class person
{
    属性:
        char gender;//性别
    行为(方法)
       void walk()
       {
           cout<<"pai~ pai~"<<endl;
       }       
};

(1)类使用步骤
1)声明类
class 类名
{
public:
成员变量(属性)
成员函数(行为/方法)
};

2)创建对象
类名 对象名
class person ps;//创建对象 也是实例化对象

3)调用类成员
 .成员变量或者成员函数
 ->成员变量或者成员函数

实例:
   #include<iostream>//input output stream  输入输出头文件
#include<string>
using namespace std;

//1.声明
class Person  //class 是声明类的关键字 Person 类名  
{
    public:
        string name;
        char gender;
        int age;
    
        void init()
        {
            name="小美";
            gender='f';
            age=18;
        }

        void walk()
        {
            cout<<name<<((gender=='f')?"女孩":"男生");
            cout<<"年龄: "<<age<<"岁"<<endl;
            cout<<"跑:pai~pai~"<<endl;
        }
        void smile()
        {
            cout<<"笑:哈哈哈~~~~"<<endl;
        }
};
int main()
{

    //2.实例化
    //class Person ps;//class可以省略
    Person ps1;//实例化对象

//3.调用
    ps1.init();//初始化person对象
    ps1.walk();
    ps1.smile();
}

练习:求圆的周长和面积
数据描述:
半径,周长,面积均用实型数表示
数据处理:
输入半径 r;
计算周长 = 2πr ;
计算面积 = π* r2 ;
输出半径,周长,面积;

    • c语言编写:
        #include<iostream.h>
        using name std;
        void main ()
        { 
	        double r, girth, area ; 		
           const double PI = 3.1415 ;
           cout << "Please input radius:\n" ; //操作符重载
           cin >> r ;  //输入
           girth = 2 * PI * r ; 
           area = PI * r * r ;
           cout << "radius = " << r << endl ; 
           cout << "girth = " << girth << endl ;
           cout << "area = " << area << endl ;
        }

要求:声明类 并实现以上功能
#include//input output stream 输入输出头文件
using namespace std;

#define PI 3.14
class Circle
{
public:
double r;//半径
void set_r(double radius)//double radius=3.0
{
r = radius;
//r=3.0;
//cout<<“请输入半径:”<<endl;
//cin>>r;
}

	void getGirth()
	{
		cout<<"周长:"<<2*PI*r<<endl;
	}

	void getS()
	{
		cout<<"面积:"<<PI*r*r<<endl;
	}

};
int main()
{
Circle c1;
c1.set_r(3.0);//调用成员函数
c1.getGirth();
c1.getS();

//Circle c2;
//c2.set_r();
//c2.getGirth();

}

(2)成员变量为数组
#include//input output stream 输入输出头文件
#include
using namespace std;

class Stu
{
    public:
        string name;
        int age;
        int score[3];

        void init(string n,int a)
        {
            name=n;
            age=a;

            cout<<"请输入3科成绩:"<<endl;
            for(int i=0;i<3;i++)
            {
                cin>>score[i];
            }
        }

        void show()
        {
            cout<<"姓名:"<<name<<endl;
            cout<<"年龄:"<<age<<endl;
            cout<<"成绩:语文 "<<score[0];
            cout<<" 英语:"<<score[1];
            cout<<" 数学"<<score[2]<<endl;
        }
};
int main()
{
    Stu s;//实例化  s.score
    s.init("小灰灰",2);
    s.show();

    Stu s1;//实例化 s1.score
    s1.init("美女",18);
    s1.show();
}

(3)成员变量为指针
#include//input output stream 输入输出头文件
#include
using namespace std;

class Stu
{
    public:
        string name;
        int age;
        //int score[3];
        int *pscore;

        void init(string n,int a)
        {
            name=n;
            age=a;

            //申请堆空间
            pscore = new int[3];
            if(NULL==pscore)
            {
                cout<<"malloc error"<<endl;
                //退出程序 或者重复申请
            }
            cout<<"请输入3科成绩:"<<endl;
            for(int i=0;i<3;i++)
            {
                cin>>pscore[i];
            }
        }

        void show()
        {
            cout<<"姓名:"<<name<<endl;
            cout<<"年龄:"<<age<<endl;
            cout<<"成绩:语文 "<<pscore[0];
            cout<<" 英语:"<<pscore[1];
            cout<<" 数学"<<pscore[2]<<endl;

        }

        void destroy()
        {
            delete []pscore;
            pscore = NULL;
        }
};
int main()
{
    Stu s;
    s.init("小灰灰",2);
    s.show();
    s.destroy();

    Stu s1;
    s1.init("美女",18);
    s1.show();
    s1.destroy();
}

作业1:创建一个产品类product 成员变量自己定义(string name,int price) 使用set函数及get函数进行赋值 及获取结果(price)
在main中创建3个产品对象并赋值 打印

作业2:定义一个类 Array,定义二维数组成员,int arr[3][4];
重载函数print(),分别实现常规打印数组元素和以一定格式打印数组

   数组初始化:init函数向二维数组中存入数据 如下:行下标i 列下标是j  arr[i][j]=i+j
    0 1 2 3
    1 2 3 4 
    2 3 4 5 
   
print() 函数打印3行4列的二维数组--常规格式


print(char sp);//sp可以是某个字符 打印输出如下
0#1#2#3 
1#2#3#4 
2#3#4#5

class Array
{
public:
int arr[3][4];
void init()//初始化数组
{

    }
    
    void print()//常规格式
    {}
    
    void print(char sp)//加#的打印
    {
        
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

encounter♌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值