c++快速入门

本篇文章记录学习c++的这几日,c++其实就比c多了一点内容,如:类,继承,多态..面向对象的内容,如果你学习过C语言,学C++就非常简单,本文章写的比较简单,适合快速入门

文章目录

  • 一、入门基本操作 
    • 概述
    • 安装环境
    • c++输入输出
    • 数据类型
    • 赋值运算,算数运算,关系运算,逻辑运算
  • 二、分支结构
    • if语句
    • if嵌套
    • 多条件if语句
    • 三目运算符
    • switch语句
  • 三、循环结结构
    • while语句
    • do...while语句
    • for语句
    • 循环嵌套
    • goto语句
  • 四、函数
    • 函数定义和声明
    • 变量的作用域
    • 函数参数传递
    • 函数分文件编程
    • 函数递归
  • 五、指针
    • 指针的概念
    • 使用指针
    • 指针作为函数的参数
    • const修饰指针
    • void类型指针
    • 内存模型
    • 动态分配内存new和delete
    • 二级指针
    • 函数指针和回调函数
  • 六、数组
    • 数组的概念
    • 一维数组和指针
    • 数组作为函数参数
    • 动态创建一维数组
    • 数组越界
    • 二维数组
    • 二维数组作为函数参数
  • 七、结构体
    • 结构体概念
    • 结构体指针
    • 结构体数组
    • 结构体嵌套
    • 简单链表
  • 八、共用体
  • 九、引用
    • 引用的基本概念
    • 引用作为函数参数 
    • 引用作为函数返回值
  • 十、函数的重载
    • 默认函数参数
    • 函数重载、
  • 十一、类
    • 类的概念
    • 类的使用
    • 构造函数和析构函数
    • 拷贝构造函数
    • 浅拷贝和深拷贝
    • 初始化参数
    • const修饰成员函数
    • this指针
    • 静态成员变量
    • 友元
    • 重载运算符
    • 继承
    • 多态

一、入门基本操作


  1. 概述

c++语言是一门面向对象的编程,它的优点是容易维护,出现问题可以精确定位到。在C语言基础上的特征主要有:类及派生类、共有和私有成员、构造函数和析构函数、友元、内联函数、赋值运算符的重载,等等。

     2.安装环境

因为我经常玩Linux,一般在Linux上面开发,先安装编译工具g++,在安装所需要的库就行了,你们也可以用其他环境,只要能编译c++代码就行了。

   3.c++输入输出

        输出

        当前是没有声明缺省空间

#include <iostream> //头文件

int main()
{
    std:cout <<"打印的内容";
    std:cout <<"打印的内容"<<endl; //endl这个相当于是换行    

    return 0;
}

        声明缺省空间,就可以进行简写

#include <iostream>

using namespace std;//声明缺省命名


int main()
{
    cout << "打印的内容"<<endl;
    
    return 0;
}

        输入

#include <iostream>
using namespace std;//声明缺省命名


int main()
{
    string name;//定义一个变量

    cin >> name;//c++里面是不需要占位符的,可直接输出
    cout << "name:"<<name<<endl;

    return 0;
}

  4.数据类型

c++常用的数据类型:整型,浮点型,字符型,字符串型(string),布尔类型,指针类型在

#include <iostream>
using namespace std;

int main()
{
    //1.整型
    int id;
    
    //2.浮点型
    float score; //其中有效位数为7位
    double scores;//其中有效位数为15-16位
    
    //3.字符型
    char c; //存放到内存里面是ascll码,表示范围0-1297
    
    //4.字符串型
    string name="lijianhua";//用+号可以拼接字符串的内容
    name = "姓名"+name+"作者";

    

    //5.布尔类型
    bool yz;//返回true/false,true=1,false=0;
    //布尔类型本质就是一个整形可以用于相加
    boo zz;
    cout<<yz+zz;

    return 0;
}

 在c++如何表示二进制,八进制,十六进制?

二进制加上0b或0B,八进制加上0,十六进制加上0x

  转义字符 \

在Ascll表中除了字符还有一些不能直接表示的特殊字符,比如: LF/NL,换行符,所以我们要有 \n 进行转义

 强制类型转换

#include <iostream>
using namespace std;

//强制转换就是, 把一种数据类型转换成另外一种数据类型
int main()
{
   int sum = 17, count = 5;
   float mean;
 
   mean = (flaot) sum / count;
    
    cout<<mean;  
}

5.赋值运算,算数运算,关系运算,逻辑运算

     赋值运算

#include <iostream>
using namespace std;

int main()
{
    int a,b,c;
    
    a=b=c=2;//在赋值运算下,是从右自左运算
    
    cout<<"a="<<a<<endl;
    cout<<"b="<<b<<endl;
    cout<<"c="<<c<<endl;

    //赋值运算 +=,-=,*=,/=,%=;
    
    c+=b;//表示c = c+b;依次类推,字符串只能用=赋值
    

    
}

    算数运算

#include <iostream>

using namespace std;

int main()
{
    //算数运算就是加减乘除取余
    int a=4,b=2,tmp=0;
    
    tmp = a+b;
    cout<<"a+b="<<tmp'
    
    tmp = a-b;    
    cout<<"a-b"<<tmp;
    
    tmp = a*b;
    cout<<"a*b="<<tmp;
    
    tmp = a/b;
    cout<<"a/b="<<tmp;
    
    tmp = a%b;
    cout<<"a%b"<<tmp;

    //当多个算数运算一起的时候 是从 左到右依次计算(先乘除后加减),如果有括号,要先算括号里面的
    
    int  c=2;
    
    tmp = a+b*c;
    cout<<tmp;
    

    return 0;
}

   关系运算

#include <iostream>

using namespace std;

int main()
{
    //关系运算有>,<,==,>=,<=,!=;一般使用关系运算用()括起来
    
    int a=3,b=4;
    bool tmp;
    
    tmp = (a > b);
    cout<<tmp;//如果a>b是真的,那就返回true,也就是1,依次类推如果 >=;
    
    tmp = (a >= b);
    cout<<tmp;
    
    return 0;
}

 逻辑运算

#include <iostream>

using namespace std;

int main()
{
    //逻辑运算有 &&,||,!,使用用括号括起来

    int a=3,b=4;
    bool tmp;
    
    tmp = (a && b);//两个表达式都是真的才返回true
    tmp = (a || b);//只要1个表达式为真就返回true
    tmp = (!a);    //将当前状态进行取反,原本是真进行取反就变成了假
    

    return 0;
}

二、分支结构

1. if语句

#include <iostream>

using  namespace std;

int main()
{
    int flag;
    
    cout<<"1 == OPEN,0 == CLOSE"<<endl;
    cin >>flag;

    if(flag)
    {
        cout<<"打开成功"<<endl;
    }
    else
    {
        cout<<"关闭"<<endl;
    }
        

    return 0;
}

2. if嵌套

#include <iostream>

using  namespace std;

int main()
{
    int flag;
    
    cout<<"1 == OPEN,0 == CLOSE"<<endl;
    cin >>flag;

    if(flag)
    {
        cout<<"打开成功"<<endl;
        
        if(flag)
        {
            cout<<"谢谢"<<endl;
        }
        else
        {
            cout<<"滚"<<endl;       }
        }

    }
    else
    {
        cout<<"关闭"<<endl;
    }
        

    return 0;
}

   3. 多条件if语句  

#include <iostream>

using  namespace std;

int main()
{
    int flag;
    
    cout<<"1 == OPEN,0 == CLOSE"<<endl;
    cin >>flag;

    if(flag)
    {
        cout<<"打开成功"<<endl;
    }
    else if(flag == 0)
    {
        cout<<"关闭"<<endl;
    }
    else
    {
        cout<<"您输入有误"<<endl;
    }
        

    return 0;
}

 4.  三目运算

#include <iostream>

using namespace std;

int main()
{
    int a=3,b=4,tmp=0;

    tmp = a>b?a:b;//如果第一个表达式是真就把a赋给tmp,假就把b赋给tmp
    cout<<tmp;
    
    tmp = (a>b?a:b)>tmp?(a>b?a:b):b;
    cout<<tmp;    

    return 0;
}

5.switch语句

#include <iostream>

using namespace std;

int main()
{
    int tmp;    
 
   cout<<"请输入您的id"<<endl;
   cin>>tmp;

    switch(tmp)
    {
        case 1:
        
              cout<<"这是id1"<<endl;
              break;
        case 2:
                cout<<"这是id2"<<endl;
                break;
        default:
                cout<<"输入有误"<<endl;
                break;
        
    
    }
    
    //break用于打断离他最近的case或者while,for;

    return 0;
}

三、循环结结构

  1. while语句
#include <iostream>

using namespace std;

int main()
{
    int flag = 1;
    
    while(flag <= 3) //表达式,然后在判断
    {
        cout<<"这是执行了第"<<flag++<<"次"<<endl;
            
    }

    return 0;
}

        2.do..while语句

#include <iostream>

using namespace std;

int main()
{
    int flag = 1;
    
    do//运行do..while 至少会被执行一次
    {
        cout<<"执行第"<<flag++<<"次"<<endl;
    
    }while(flag <=  3);

    return 0;
}

        3.for语句

#include <iostream>

using namespace std;

int main()
{
    int i;
    
    for(i =1;i<= 3,++i )
    {
        cout<<"执行第"<<i<<"次"<<endl;
    }
  
  

    return 0;
}

 4.循环嵌套

#include <iostream>

using namespace std;

int main()
{
    int i,j;
    
    for(i =1;i<= 3;++i )
    {
        for(j=1;j<=2;++j)
        {
            cout<<"第"<<i<<"组的第"<<j<<"人"<<endl;
        }
    }
  
 

    return 0;
}

5.goto语句

#include <iostream>

using namespace std;

int main()
{
 
    int i =1;

    cout<<"第一个"<<endl;
    
    b:
    cout<<"第三个"<<endl;
    i++;        
    if (i <= 2)
    goto b;
    
    cout<<"第二个"<<endl;    

    //goto语句会跳转到你语句标号的那条语句去
      

    return 0;
}

四、函数

  1. 函数的定义和声明
#include <iostream>

using namespace std;

int add(int a,int b);//函数声明,因为函数定义的时候在主函数后面,其作用域不一样,进行函数声                
                       明,方可能访问到此函数

int main()
{
    int max,a,b;
    
    cin>>a b;
    
    max = add(a,b);//函数的调用
    
    cout<<max<<endl;
    
    return 0;
}


int add(int a,int b)//函数的定义由函数返回的数据类型,函数名,函数的形参数据类型组成
{
    if(a > b)
    {
        return a;
    }
    else if(b > a)
    {
        return b;
    }
    else
    {
        cout<<"a == b"<<endl;
    }
    
}

     2.变量的作用域

#include <iostream>

using namespace std;

int handler();

int b = 1;

int main()
{
    //作用域有局部和全局,在语句块内部的变量成为局部变量,在函数外定义的变量成为全局变量

    int a=2;
    int b = 1;
    handler();
    cout<<"b="<<::b<<endl;//程序运行过后b=2,因为全局变量是所有函数都能访问到的变量
    cout<<"a="<<a<<endl;//当前语句块能访问a变量

    //如果全局变量和局部变量的变量名冲突了,我们想调用全局变量,就在变量名前加::
     cout<<"局部变量="<<b<<endl<<"全局变量="<<::b<<endl;

    //局部变量生命周期,函数返回,就释放 存储在栈区
    //全局变量生命周期,程序结束,释放   存储在静态存储区     

    //static修饰静态变量,static默认只初始化一次,程序结束,生命周期才结束  存储在静态存储区  

    cout << handler();

    return 0;
}

int handler()
{
        static int c = 2; //不管函数调用几次,只会被初始化一次       
        c++;

        cout<<"b ="<<b++<<endl;

       //cout<<a;//当前函数访问不到a变量,因为是局部变量,只能在语句块它所定义的地方,才能访问     

        return c;
}

   3.函数参数传递

#include <iostream>

using namespace std;
int  handler(int a);


int main()
{
    int a = 0;
    handler(a);//传参的时候我们传的参数就是实参,而函数自己写的参数是形参
                //函数只是把我们传的参数拷贝一遍,不管函数内如何改变参数的值,都不会影响到实参,                    
                 因为它只是一个复制品,能改变实参就要用到指针
    
    cout<<a<<endl;

    return 0;
}

int handler(int a)
{
       a = 1000;


}

  4.函数分文件编程 

分文件编程,就是把函数所实现的模块代码按照不同的功能放到对应的文件中去,我们main函数需要那个功能,就添加对应的文件

#include <iostream>
#include "add.h"   //添加对应的头文件

using namespace std;

int main()
{

    int a,b,tmp;
       
    tmp = add(a,b);

    cout<<tmp;    

    return 0;
}

   add.h

#include <iostream>

using namespace std;

int add(int a,int b);//添加函数声明

    add.c 

函数功能模块代码实现

#include "add.h"  

int add(int a,int b)
{
    if(a > b) return a;
    else if (b > a) return b;
    else return -1;
}

  5.函数递归

函数递归就是函数自己调用自己,要有函数终止的条件,运用了栈的先进后出原理

#include <iostream>
using namespace std;

int add(int a);

int main()
{
     int tmp;

     tmp = add(100);
     cout<<tmp;

    return 0;
}

int add(int a)
{
    if(a == 0) return 0;

    return a+add(a-1);
}

 五、指针

   1.指针的概念

在c++中,一个变量会根据变量的数据类型来分配内存,我们如果想操作变量或者更改变量的值,那我们就必须知道变量的地址,进行操作,而指针就是存放普通变量的地址,指针会存放变量的起始地址

  2.使用指针

#include <iostream>

using namespace std;

int main()
{
    //取地址用&,取地址的值用*

    int a = 3;
    int *p = &a;

    cout<<"a的地址是"<<&a<<endl<<"a的值="<<a<<endl;
    cout<<"p存放的地址是"<<p<<endl<<"p指向地址存放的值是="<<*p<<endl;

    *p = 4;
    cout<<"更改后的值="<<a;

    return 0;
}

  3.指针作为函数的参数

#include <iostream>

using namespace std;

void handler(int *p);//指针作为形参,指向传过来的实参的地址,就可以改变实参的值

int main()
{
    int a = 0;

    handler(&a);
    cout<<a;

    return 0;
}

void handler(int *p)
{
    *p = 1;
}

  4.const修饰指针

#include <iostream>

using namespace std;


int main()
{
    int a = 0;
    int b = 0;
    const int *p = &a;//常量指针,表示可以指向其他变量的地址,但是不能更改其变量的值
    p = &b;
    //*p = 2;//error  

    int * const p = &a;//指针常量,表示可以更改变量地址的值,但是不能重新指向其他变量的地址
    *P = 1;
    //p = &b;//error

    const int * const p = &a;//既不能指向其他变量地址,也不能更改其他变量地址的值,只能引用
    cout<<a;


    return 0;
}

    5.void类型指针

void类型不是没有,是任意类型指针,可以是int,char,float...,是一个不确定的指针,但是你用的时候强转成你用的指针就可以了

   6.内存模型 

内核空间

栈 :局部变量 函数的形参及返回值

堆 :存放动态分配的内存

数据段:存放全局变量 常量

代码段 :存放可执行的代码

模型依次是从下到上

 7.动态分配内存new和delete

#include <iostream>

using namespace std;

int main()
{
    int a = 0;
    int *p =NULL;//为防止野指针
    
    p=new int(3);//分配动态内存 并给分配的地址传入参数

    cout<<"分配的地址:"<<p<<"值:"<<*p<<endl;

    delete p;//动态分配的内存使用完 一定要进行删除 防止内存泄漏

    return 0;
}

 8.二级指针

#include <iostream>

using namespace std;

int main()
{
    int a = 0;
    int *p = &a;//一级指针指向普通变量的地址
    int **q = &p; //二级指针指向指针变量的地址   

    cout<<"a的地址"<<&a<<endl<<"a的值:"<<a<<endl;
    cout<<"p指向的地址"<<p<<endl<<"怕指向地址的值:"<<*p<<endl;
    cout<<"q指向的地址"<<q<<endl<<"q指向的地址的地址"<<*q<<endl<<"q指向地址的地址值"<<**q;

    return 0;
}

 9.函数指针和回调函数

        函数指针

#include <iostream>

using namespace std;
void handler(string *p);

int main()
{
    string a = "lijianhua";

    void (*p)(string *p);//函数指针本质上就是一个指针,只不过这个指针指向函数
                          //定义一个函数指针,要更函数一样的返回值,形参列表                  
    p=handler;
    p(&a);

    return 0;
}

void handler(string *p)
{
       cout<<*p<<endl;
}

        回调函数

#include <iostream>

using namespace std;
void handler(void (*p)(int),int a);
void iverson(int a);
void lijianhua(int a);

int main()
{
    int a = 1;
    //回调函数就是一个函数作为另一个函数的参数,把自己变成一个参数,供调用其他函数

    handler(lijianhua,a);
    handler(iverson,a);
    

    return 0;
}

void handler(void (*p)(int),int a)
{
       p(a);
}

void lijianhua(int a)
{
    cout<<"a="<<a;
}

void iverson(int a)
{
    cout<<"a="<<a;
}
 

六、数组

1.数组的概念

数组存放的是相同的数据类型,是一块连续的内存,数组名保存的是第一个元素的地址,通过下标来访问数组的内容

2.一维数组和指针 

#include <iostream>

using namespace std;

int main()
{
    //数组的定义方式
    int arry[3]={1,2,3};//定义同时赋值
    int arry1[3]={0};
    arry1[0] = 1;
    arry1[1] = 2;
    arry1[2] = 3;//先定义在赋值    
    
    int *p=NULL;
    p = arry;//指向数组第一个元素的地址
    
    for(int i=0;i<3;++i)
    {
        cout<<"第"<<i<<"个元素="<<arry[i]<<endl;//通过下标访问
        cout<<"第"<<i<<"个元素="<<*(p+i)<<endl; //通过指针访问
    }
    

    return 0;
}

3.数组作为函数参数

#include <iostream>

using namespace std;
void Brry(int *p,int len);
void Arry(int a[],int len);


int main()
{

    int arry[3]={1,2,3};

    Arry(arry,3);
    Brry(arry,3);

    return 0;
}

void Arry(int a[],int len)//此时int a[] 占8个字节,相当于是一个指针
{

    for(int i=0;i<len;++i)
    {
        cout<<"第"<<i<<"个元素="<<a[i]<<endl;
    }
}


void Brry(int *p,int len)
{

    for(int i=0;i < len;++i)
    {
        cout<<"第"<<i<<"个元素="<<*(p+i)<<endl;
    }
}

4.动态创建一维数组

#include <iostream>

using namespace std;

int main()
{

    int *p = new int[8];//表示分配8个元素的整型数组
    
    for(int i=0;i<8;++i)
    {
        *(p+i) = i;//等同于p[i]
    }
    
    for(int i=0;i<8;++i)    
    {
        cout<<"第"<<i<<"个元素="<<*(p+i)<<endl;
    }

    delete []p;//释放内存
  

    return 0;
}

5.数组越界

因为数组的内存是连续存储的,假如我有3个元素,那对应这3个元素的地址都是连续的,我p指向了第一个元素,p+1就指向了下个元素的地址,当p+3的时候,就越界了,因为根本没有第四个元素

#include <iostream>

using namespace std;

int main()
{

  int arry[3]={1,2,3};
  int *p = &arry[1];

  cout<<*p<<endl;
  cout<<*(p+1)<<endl;
  cout<<*(p+2)<<endl;      //这块输出的是垃圾值,因为它越界了
  
   return 0;
}

 6.二维数组

#include <iostream>

using namespace std;

int main()
{
    //二维数组的定义

    int arry[2][3]={1,2,3,4,5,6};//可以这样赋值
    int arry1[2][3]={{1,2,3},{44,5,6}};//第二种方法
    int arry3[][3]={1,2,3,4,5,6};//可以不写行数

    //二维数组也是块连续的内存,[2][3]从0行0列---1行2列,

    int *p = (int *)arry;//这里要进行强转因为指向二位数组,应该用数组指针

    for(int i=0;i < 6;++i)
    {
           cout<<"第"<<i<<"个元素="<<*(p+i)<<endl;
    }

    //也可以这样输出

    for(int i=0;i<2;++i)
    {
            for(int j=0;j<3;++j)
            {
                    cout<<"第"<<i<<"行"<<j<<"列="<<arry[i][j]<<endl;
            }
    }



    return 0;
}

7.二维数组作为函数参数

#include <iostream>

using namespace std;
void Arry(int (*p)[4],int len);

int main()
{

        int arry[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
        int i,j;        
        

        Arry(arry,3);



    return 0;
}


//p 保存的是首地址,(*p)表示的是第0个元素的地址,*(*p),第0个元素地址的值

void Arry(int (*pr)[4],int len)
{

        int i,j;

        for(i = 0; i < len; i++)
        {
                for(j = 0; j < 4; j++)

                cout<<*(*(pr+i)+j);

        }


}

七、结构体

 1.结构体概念

数组存放的是相同的数据类型,结构体存放的是不同的数据类型

#include <iostream>
#include <string.h>

using namespace std;

struct student
{
        int id;
        char name[12];
}s1;//可以在这里声明结构体变量



int main()
{
    struct student s1;//也可以在这里声明结构体变量,也可以边定义边赋值

    s1.id = 99;
    strcpy(s1.name,"iverson");

    cout<<"id="<<s1.id<<endl<<"name="<<s1.name<<endl;
    //调用的时候用.进行调用,如果是结构体指针,就用->


    return 0;
}

  2.结构体指针

#include <iostream>
#include <string.h>

using namespace std;

struct student
{
        int id;
        char name[12];
        char *p1;

};


int main()
{
    struct student *p= new struct student[100];//动态分配内存
    strcpy(p->name,"lijianhua");
    p->id = 100;

    cout<<"name="<<p->name<<endl<<"id="<<p->id<<endl;
    p->p1 = (char *)"lijanhua";

    return 0;
}

 3.结构体数组

#include <iostream>
#include <string.h>

using namespace std;

struct student
{
    int id;
    char name[12];
};


int main()
{

    struct student t1[3];//定义了三个结构体

    for(int i=0;i<3;++i)
    {
        t1[i].id=i;
        cin>>t1[i].name;

    }

    for(int i=0;i<3;++i)
    {
        cout<<"第"<<i<<"个元素="<<t1[i].id<<endl<<"第"<<i<<"个名字="<<t1[i].name<<endl;
    }

    return 0;
}

 4.结构体嵌套

#include <iostream>
#include <string.h>

using namespace std;

struct teacher
{
    char name[128];
};


struct student
{
    int id;
    struct teacher t1;

};


int main()
{

    struct student t2;
    t2.id=1;
    strcpy(t2.t1.name,"Li teacher");
    cout<<t2.id<<endl<<t2.t1.name<<endl;


    return 0;
}

 5.简单链表

链表用于存储离散的数据类型,我用的尾插法,一共分为两部分,数据域,和指针域,定义一个头指针和尾指针,尾指针始终指向新节点

#include <iostream>

using namespace std;
struct student* create();
int out(struct student *head);


struct student
{
    int id;
    struct student *next;
};


int main()
{
    struct student *t1 = NULL;

    t1 = create();
    out(t1);

    return 0;
}

struct student* create()
{
        int len;
        int values;
        struct student *head = new struct student[256];
        struct student *last = head;

        last->next = NULL;

        cout<<"请输入您要创建节点的个数"<<endl;
        cin>>len;

        for(int i=0;i<len;++i)
        {

            struct student *New = new struct student[256];

            cout<<"请输入第"<<i+1<<"个节点的值:";
            cin>>values;

            New->id = values;
            last->next = New;
            last = New;
            New->next = NULL;

        }

        return head;

}

int out(struct student *head)
{

        struct student *p = head->next;


        if(p == NULL)
        {
                cout<<"没有节点"<<endl;
                return -1;
        }


        while(p != NULL)
        {
                cout<<p->id<<endl;
                p = p->next;
        }


}

 八、共用体

共用体本质上就是共用一块内存,一次性只能输出一个变量的值,如果有多个变量被赋值,只会执行最后一个赋值的变量

#include <iostream>
#include <string.h>

using namespace std;

union student
{
        int a;
        char name[12];
};


int main()
{
        union student t1;
        t1.a  =1;
        strcpy(t1.name,"lijianhua");

        cout<<t1.a<<endl;
        cout<<t1.name<<endl;

    return 0;
}

运行结果:
        145112531
        lijianhua    

 九、引用

1.引用的基本概念

引用就是取别名,和引用的变量共享一段内存,可以多个引用一个变量,但是不能空引用

#include <iostream>

using namespace std;

int main()
{
    //引用的用法  数据类型 &变量 = 变量(必须是一样的数据类型)

    int a=2;
    int &ra = a;//给变量a取别名
    
    cout<<a<<endl<<&a<<endl;
    cout<<ra<<endl<<&ra<<endl;    

    
    return 0;
}

运行结果:
    2
    0x7ffe4dc69a1c
    2
    0x7ffe4dc69a1c

 2.引用作为函数参数

#include <iostream>

using namespace std;
void handler(int &ra);

int main()
{
    int a=2;
  
    handler(a);
    cout<<"a="<<a<<endl;
    
    return 0;
}

//因为ra引用a,就是a的别名,这里ra就是a了,跟指针作用一样,可以改变实参的值

void handler(int &ra)//作用如同指针常量,int* const ra,可以改变其值,但是不能改变指向的变量
{
    ra = 3;

}

运行结果:
        a=3

3.引用作为函数返回值

#include <iostream>

using namespace std;

//把引用作为返回值
double arrs[5]={12.94,23.56,12.0,9.43,45.63};

double& setValues(int i)
{
   return arrs[i];
}

int main()
{

        //引用作为i返回值返回的是引用的变量本身,但是一定要全局变量或者static,否则由于作用域,变量会被提前回收    

    cout<<"改变前的值:"<<endl;
    for (int i = 0; i < 5; i++)
    {
        cout<<"arrs["<<i<<"]:"<<arrs[i]<<endl;
    }
    
    //改变其中的两个元素
    setValues(1)=11.11;
    setValues(3)=33.33;
    
    cout<<"改变后的值:"<<endl;
    
    for (int i = 0; i < 5; i++)
    {
        cout<<"arrs["<<i<<"]:"<<arrs[i]<<endl;
    }
}
~ 

十、函数重载

1.默认函数参数

函的形参在定义的时候,可以先赋值,我调用的时候,可以赋值的形参传参,也可以不传

#include <iostream>

using namespace std;

void handler(int a,string b ="lijianhua")
{
        cout<<a<<endl<<b<<endl;
}

int main()
{
        int a = 2;

        handler(2,"dddd");
        handler(2);

        return 0;
}

2.函数重载 

在定义函数的时候。可以用相同的函数名字,但是形参必须不一样(形参顺序也不能一样,有默认函数参数也不行)

#include <iostream>

using namespace std;

void handler(int &a,int &b)
{
    int tmp;tmp = a;a = b;b = tmp;
}

void handler(string &a,string &b)
{
    string tmp; tmp = a, a = b;b = tmp;
}


int main()
{
    int a=1,b=2;
    string c = "lijianhua";
    string d = "iverson";

    handler(a,b);
    handler(c,d);

    cout<<a<<endl<<b<<endl;
    cout<<c<<endl<<d<<endl;

    return 0;
}

 十一、类

1.类的概念

我们可以理解为一个数据类型,这个数据类型是复合的,它既有数据又有函数。它和结构体的区别就是,结构体不能定义函数,而它可以

 2.类的使用

#include <iostream>

using namespace std;

//声什么属性都不写 默认就是private

class student
{

public: //公共属性

        int name;
        void handler();//成员函数 由类变量调用
        void handler(int a1,int b1);
private: //私有属性
        int a;
        int b;

};

int main()
{
        class student t1;//定义一个类的变量
        //也可以直接用类名定义变量 类名 变量
     
        t1.handler(2,3);
        t1.handler();

}


void student::handler()
{
        cout<<a<<endl<<b<<endl;
}

void student::handler(int a1,int b1)//在类的外面定义 要用类名::
{
        a = a1;
        b = b1;
}

3.构造函数和析构函数

     构造函数

构造函数在定义一个类的时候就有,如果程序员没有手动定义,编译器默认也会定义一个,一般用于承担初始化工作

#include <iostream>

using namespace std;

//构造函数就是用类名 形参组成,可以写多个构造函数,支持重载,也可以在类外面定义
//只有在创建类变量的时候才会调用构造函数,不能手动调用,但是可以直接调用
//必须是public权限

class student
{

public:
        int name;
        int  score;
        student();
        student(int name1,int score1)
        {
                name = name1;
                score = score1;
        }

};



int main()
{
        class student t1(2,99);//隐式调用
        class student t2;//创建的时候不带括号 默认就调用没有形参的构造函数
        t2.name  = -1;
        t2.score = -1;

        cout<<t2.name<<endl<<t2.score<<endl;

        cout<<t1.name<<endl<<t1.score<<endl;
        
        class student t3 = student(2,3);//也可以这样调用,叫做显示调用,一般不这么调
}

student::student()
{
        cout<<"这是地一个构造函数"<<endl;
}

   析构函数

在开辟空间时,需要构造函数来开辟空间,对应,作用域退出时也需要一个函数做“收尾”的工作,与构造函数对应——析构函数

析构函数和构造函数作用相反,用于释放对象的内存空间

如果程序员未写构造函数,那么系统也会提供一个默认的构造函数,同样,如果程序员未写析构函数,那么系统也会提供一个默认的析构函数,在当前对象退出时,自动调用,进行释放空间。析构函数在对象生命周期结束后指向

#include <iostream>

using namespace std;

//一个构造函数仅此只要有一个析构函数
//析构函数语法 ~类名

class student
{

public:
        int name;
        int  score;
        student();
        student(int name1,int score1)
        {
                name = name1;
                score = score1;
        }

        ~student();//析构函数也可以在类外面定义,

};


int main()
{
        class student t2;
        t2.name  = -1;
        t2.score = -1;

        cout<<t2.name<<endl<<t2.score<<endl;

}

student::student()
{
        cout<<"这是地一个构造函数"<<endl;
}

student::~student()
{
        cout<<"这是一个系够函数"<<endl;
}

 4.拷贝构造函数

同一类型的对象复制成员值来初始化对象(当出现类的 “=” 赋值时,就会调用拷贝构造函数),拷贝构造函数如果没写,编译器会自动生成一个拷贝构造函数

#include <iostream>
#include <string.h>

using namespace std;

class student
{

public:
        int id;
        int *score;

        student ()
        {
                cout<<"够找函数"<<endl;
        }

        student(student &s)//拷贝构造函数
        {
                id = s.id;
                score = new int;
                *score = *s.score;
                cout<<"拷贝构造函数"<<endl;
        }

        ~student()//delete堆内存
        {
                delete score;
                score = NULL;

                cout<<"系够函数执行"<<endl;
        }

};


int main()
{
        class student t1;

        t1.id =99;
        t1.score = new int(100);

        cout<<t1.id<<endl<<*t1.score<<endl;

        class student t2 (t1);//等价于 class student t2 = t1;
        cout<<t2.id<<endl<<*t2.score<<endl;


}
~ 

5.浅拷贝和深拷贝

浅拷贝就是两个对象指向同一个内存,析构函数执行delete删除了内存,另一个对象就会出现错误

深拷贝就是两个对象分别指向不同的内存 

#include <iostream>
#include <string.h>

using namespace std;

class student
{

public:
        int id;
        int *score;

        student ()
        {
                cout<<"够找函数"<<endl;
        }

        student(student &s)
        {
                id = s.id;
                score = new int;
                *score = *s.score;
                cout<<"拷贝构造函数"<<endl;
        }

        ~student()
        {
                delete score;
                score = NULL;

                cout<<"系够函数执行"<<endl;
        }

};


int main()
{
        class student t1;

        t1.id =99;
        t1.score = new int(100);

        cout<<t1.id<<endl<<*t1.score<<endl;

        class student t2 (t1);//等价于 class student t2 = t1;
        cout<<t2.id<<endl<<*t2.score<<endl;


}

 6.初始化列表

初始化列表跟在构造函数后面语法是 : 参数(值),参数(值)  ,它是在调用构造函数前就已经初始化了,解决了常量和引用,定义时必须要赋值

#include <iostream>

using namespace std;

class teacher
{

public :

        int a;
        const int b;//因为引用和常量必须在定义的时候就赋值,所以在程序执行的时候就会报错
        int &c;

        teacher(int a1,int b1,int &c1):a(a1),b(b1),c(c1)//而初始化列表是在调用构造函数前就已经初始化了
        {
                /*a= a1;
                b = b1;
                c = c1;*/

        }
        
};


int main()
{
        int arry  =100;

        class teacher t(1,2,arry);
        cout<<t.a<<endl<<t.b<<endl;
        cout<<t.c;
}

 7.const修饰成员函数

#include <iostream>

using namespace std;

class student
{
public:

        mutable int a;//mutable 可以突破不能访问const的
        mutable int b;

        student(int a1,int b1):a(a1),b(b1)
        {
                cout<<"this is my gouzhao handler"<<endl;
        }

        void handler() const; //const成员函数 
        ~student();
};

student::~student()
{
        cout<<"this is my xigou handler"<<endl;
}

void student::handler() const
{
        //a = 100;编译错误,因为在const修饰函数过后,这个函数只能读这个对象的值,不能改写了


        cout<<a<<endl<<b<<endl;
}

int main()
{
        /*class student t1(100,100);

        t1.handler();*/

        const class  student t2(200,200);//const 对象只能访问const成员函数,而非const对象可以访问任意函数
        t2.handler();
}

8.this指针

this是c++中的一个关键字,表示当前对象,只能在类中使用,*this可以表述对象,因为this是一个指针,再用的时候要this->

#include <iostream>

using namespace std;

class student
{
public:

        int a;
        int b;

        student(int a,int b)//解决重名的问题
        {
                this->a = a;//表示当前被调用的对象
                this->b = b;
        }
};


int main()
{
        class student t1(100,100);

        cout<<t1.a<<endl<<t1.b;

        return 0;
}

9.静态成员变量

#include <iostream>

using namespace std;

//如果静态成员是私有属性,在类外访问将失败

class student
{
public:
    char *name = NULL;
    static int age;//定义静态变量的时候 还必须在类的外部定义一下
    student(int age,char *name)
    {
        this->age = age;
        this->name = name;
    }

     static void show()
     {
             cout<<"age="<<age<<endl;//静态成员函数只能访问静态变量 而非静态成员可以任意访问
     }
};


int  student::age = 1;//此时存储在静态常量去区,程序结束在释放类存



int main()
{
   cout<<student::age<<endl;    //在类外可以直接访问静态成员,但是要加类名::静态成员
   student::show();

    class student t1(20,"lijianhua");

    t1.show();


    return 0;
}

10.友元

在类中,访问问私有成员,只有通过共有属性进行访问,友元提供了一种方法,可以指定谁谁谁可以直接访问私有成员,友元函数,友元类,友元成员函数

using namespace std;
class boy;

class girl
{
        public:
        void show(boy &g);
        void show2(boy &g);

};


class boy
{
        friend void handler(boy &p);//friend定义了这个函数 表示这个函数就可以直接访问类里面的私有成员
        //friend class girl;//friend定义了这个类,这个类就能访问boy的私有成员    
        friend void girl::show2(boy &g);//表示只有这个成员函数才能访问私有变量
        friend void girl::show(boy &g);

  private:
        int bigD;
  public:
        int age;
        boy(int a,int b):age(a),bigD(b)
        {
        }

};


void girl::show(boy &g)
{
        cout<<"boy的bigD="<<g.bigD <<endl;
}


void girl::show2(boy &g)
{
        cout<<"boy的bigD="<<g.bigD <<endl;
}


void handler(boy &p)
{
    cout<<"bigD="<<p.bigD<<endl;
}

/*在friend成员函数的时候要讲究一个顺序,不声明,在调用的时候会报错
 * 1.成员函数必须在类的外面定义,因为我们要frined
 * 2.girl必须在要friend之前,不然由于先后顺序,会报错
 * */




int main()
{
    class boy t(20,18);
    handler(t);

    class girl t2;
        t2.show(t);    

    return 0;
}

 11.运算符重载

在c++中,函数重载就是,可以用相同的函数名(形参和顺序不同),而运算符重载,也是类似,用operator关键字进行重载,提高代码的可读性,让代码变得美观

#include <iostream>

using namespace std;

//运算符重载 在调用的时候 顺序不能变 返回值类型必须和接受的类型相同

class Tx
{
    public:
        Tx operator +(Tx &t);
        bool operator==(Tx &t);//关系运算符重载
        void show();//赋值运算符重载
        Tx(int a):num(a)
        {

        }

    private:
        int num;

};

void Tx::show()
{
    cout<<"num = "<<this->num<<endl;
}

Tx Tx::operator+(Tx &t)
{
    this->num = this->num + t.num;
    return *this;
}

bool Tx::operator==(Tx &t)
{
        bool flag;
        if (this->num == t.num)
        {
                flag = true;
        }
        else
                flag = false;
        return flag;
}


int main()
{

        Tx t1(100);
        Tx t2(200);

        t1+t2;

        t1.show();//300 //隐式传递,先传t1,在传t2
        t2.show();//200 

        bool flag;
        flag = t1 == t2;

        cout<<flag<<endl;


return 0;
}

 new和delete重载

#include <iostream>
#include <stdio.h>

using namespace std;

class A
{
        public:
                void * operator new(size_t size);
                void operator delete(void *p);
                int num;
};

void * A::operator new(size_t size)
{
        void *p = (void *)malloc(size);
        cout<<"分配的内存地址"<<p<<endl;

        return p;
}

void A::operator delete(void *p)
{
                free(p);
                cout<<"地址:"<<p<<"已经删除"<<endl;
}


int main()
{

        A *t1 = new A ;

        t1->num = 3;

        printf("%p\n",t1);
        printf("num = %d\n",t1->num);

        delete t1;

        return 0 ;
}

12.继承

继承就是我这类继承另一个类里面的成员,我就叫做派生类,被继承的类叫做基类,就是把共同的内容封装成一个类,减少了写代码的操作

#include <iostream>

using namespace std;

/**
        在继承中,基类构造函数只能初始化基类,派生类构造函数只能初始化派生类
        派生类在调用时,先调用基类的构造函数 在调用派生类的构造函数      
 *      退出的时候先调用派生类的析构函数,在调用基类的析构函数  
 * */

class animal
{
        public:
                char *name = NULL;
                int age;

                animal(int a):age(a)
                {
                }
        private:
                int sex;
};

class dog : public animal
/*以public继承基类,基类的公有成员就是派生类的共有成员,基类受保护的成员,就是派生类的受保护的成员,基类的私有成员,派生类不能访问
  以private继承基类,继承的基类都是私有的 访问不了,基类的私有成员 也访问不了   
*/                       
{
        public:
                int s;
                void eat();
                dog(int a,int b):animal(a),s(b)//这样可以同时初始化基类和派生类,但是基类必须有写anima构造函数,且只能用于同时初始化上一级,如果现在有一个c类,就初始化不了animal类,因为只能初始化继承上一级的类
                {
                        cout<<"调用了dog构造函数"<<endl;
                }

};

void dog::eat()
{
        cout<<"够吃si"<<endl;
}


int main()
{


        dog t1(18,1);
        cout<<t1.age<<endl<<t1.s<<endl;
        t1.eat();

        return 0;
}
 多继承语法:

class A
{
public:
    int a;
};

class B
{
public :
    int a;

};

class C : public A,pubic B
{
    public :
        int a;

};

如果当前类与继承的类变量或者函数重名,可以用域修饰符,

在调用的变量前面加入类名::

C t1;
t1.A::a;
t1.B::b;
t1.a;

 13.多态

我继承了基类,和基类出现了同名函数,此时我基类只能访问基类同名函数,访问不了派生类同名的同名函数,但我现在把基类的同名函数设置成虚函数,我创建一个基类指针,指向派生类对象,此时编译器就会看你指向的是谁,就会调用对应的同名函数,引用也是同理

using namespace std;

class A
{
        public :
        virtual    void show();
};

void A::show()
{
        cout<<"this is A"<<endl;
}

class B:public A
{
        public:
                void show();
};

void B::show()
{
        cout<<"this is B"<<endl;
}

class C:public A
{
        public:
                void show();

};
void C::show()
{
        cout<<"this is C"<<endl;
}

int main()
{
        A * t1 = NULL;
        int flag;

        cout<<"(1)访问A--(2)访问B---(3)访问C"<<endl;
        cin>>flag;

        switch(flag)
        {
                case 1:
                        t1 = new A;//指向哪个对象就访问该对象的同名函数
                        break;
                case 2:
                        t1 = new B;
                        break;
                case 3:
                        t1 = new C;
                        break;
                default:
                        break;
        }

        if(t1 != NULL)
        {
                t1->show();
                delete t1;
        }
}

  • 8
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《算法笔记》是由胡凡编写的一本关于算法学习的教材,它最初以C/C++为主要编程语言。这本教材主要面向想要学习算法的初学者,以及希望进一步提升算法能力的人群。 《算法笔记》的内容广泛而且深入,涵盖了很多算法的基础知识和主要思想,如递归、排序、查找、图论、动态规划等。通过学习这本教材,读者可以掌握这些算法的基本原理和实现方法,提高解决实际问题的能力。 该教材有几个特点:首先,它提供了很多例子和习题,帮助读者巩固所学的知识;其次,它介绍了很多常用的数据结构,如数组、链表、栈、队列等,读者可以通过学习这些数据结构更好地理解和应用算法;最后,它还介绍了一些高级主题,如高级数据结构、算法优化等,这些内容对于进一步提升算法水平非常有帮助。 《算法笔记》是一本入门级的教材,因此在阅读时需要一些基本的编程知识和逻辑思维能力。该教材的语言简洁明快,适合作为学习参考书,同时也可以作为算法竞赛的辅助教材。 总而言之,《算法笔记》是一本很好的算法学习教材,它以C/C++为编程语言,全面介绍了算法的基本知识和常用方法,适合想要学习算法的初学者。无论是学术研究还是实际应用,阅读《算法笔记》都能提升算法能力,并为进一步学习和应用算法打下坚实的基础。 ### 回答2: 《算法笔记 胡凡 c/c 快速入门pdf》是一本介绍算法和C/C++编程语言入门书籍。该书的作者是胡凡,它主要规划了算法的学习路径以及基本的C/C++编程语言。这本书适合初学者快速入门,对于想要系统学习算法和C/C++编程的人来说是一本不错的选择。 这本书的内容非常系统和全面。它以算法和数据结构为基础,包括基本排序、查找、图论等算法的介绍和实践,让读者能够快速掌握这些算法的原理和实现方法。同时,它还介绍了C/C++语言的基础知识和编程技巧,帮助读者理解和运用这些知识。 书中每章都有一些练习题,帮助读者巩固所学的知识。同时,每个章节末尾还提供了一些进阶的题目和参考答案,供读者深入学习和自我检测。这样的设计能够帮助读者更好地理解和掌握所学的内容。 总的来说,《算法笔记 胡凡 c/c 快速入门pdf》是一本很好的算法和C/C++入门书籍。它能够帮助读者快速了解算法和数据结构的基础知识,并学会使用C/C++语言进行编程。无论是对于想要入门算法和C/C++编程的初学者,还是已经有一定基础的读者,这本书都是一个很好的选择。 ### 回答3: 《算法笔记:胡凡C/C++快速入门PDF》是一本很棒的入门算法书籍。这本书主要介绍了常用的数据结构与算法,并通过C/C++语言来实现这些算法。 首先,这本书非常适合算法初学者。它从基础的数据结构开始讲解,如数组、链表、栈和队列,然后逐渐引入更复杂的数据结构,如二叉树、图和堆。此外,书中还介绍了常用的排序和查找算法,如冒泡排序、快速排序、二分查找等。每个算法都配有具体的代码实现和详细的解释,帮助读者理解算法的原理和应用。 其次,这本书的学习资料丰富。书中提供了很多例题和习题,读者可以通过实践来巩固所学的知识。此外,书中还介绍了一些常见的算法优化技巧和设计思路,提供了一些高效解决问题的方法和思考方式。 最后,这本书的编写风格简明易懂。作者通过清晰的语言和简洁的代码,将复杂的算法问题简化为易于理解的部分。不论是对于算法初学者还是对于有一定编程基础的读者,这本书都是一本很好的学习资料。 总而言之,《算法笔记:胡凡C/C++快速入门PDF》是一本很好的入门算法书籍。它适合初学者学习和理解常用的数据结构与算法,通过具体的代码实现和详细的解释帮助读者掌握算法的原理和应用。无论是编程初学者还是有一定基础的读者,都可以从这本书中获得丰富的知识和实践经验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

No Iverson

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

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

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

打赏作者

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

抵扣说明:

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

余额充值