[2] C++复合数据类型编程

week10

入栈出栈示意图

for循环出入栈

Day1

函数的基本使用

函数作用 : 

  • 把功能进行拆分,保证main函数有可读性
  • 函数把代码进行封装,保证重用,减少写代码的难度

函数注意点 :  函数不允许嵌套 , 函数的定义需要在main外边

函数定义的语法 :  返回值 函数名(函数参数){函数体} void FunName (FunParams) {FunMain}

函数调用 : 函数名(参数) FunName(Params)

函数返回值 :  

  • 如果函数有返回值,可以用一个相同类型的变量接收 。 不使用函数的返回值,可以不用变量去接收。
  • 如果函数的返回值是void(没有返回值) 不需要用变量接收。

函数参数 :  形式参数(形参)  实际参数(实参)

  形式参数

  • 在函数的声明或者定义(实现)小括号中出现的都是形式参数,在函数调用的小括号中出现的都是实际参数
  • 函数调用中,把实参的值传给形参,再去函数体中执行逻辑(值传递)

  默认参数

    void fun(int i = 10;); 函数声明

    fun(int i){}; 函数定义 默认写在函数声明的时候

  值传递   在函数内部对变量进行更改之后,不会影响函数外部的变量(简单类型【int float】和字符串)
  如果是数组,那么使用的就不是值传递,在函数内部更改之后会影响函数外部的值,数组使用的是地址传递

函数重载 Overload  函数重写 Override

  函数重载的定义 :

  • 函数名相同,函数参数的个数,类型或者顺序不同 
  • 函数返回值并不是函数重载的判断标准
  • 当默认参数和函数重载同时存在的时候避免二义性
  • 函数重载的本质   命名倾轧

Day2

 文件读写

// 把内存中的数据保存到硬盘中的某个文件中
    // 包含头文件(<fstream>) file stream 
    // 定义变量 ofstream  output file stream 
    // 打开文件  bianliang.open()   
    // 写内容  << 把内容写到ofstream变量中
    // 关闭文件 close()
    //ofstream Out;
    //// 打开文件,如果文件不存在会自动创建
    //// 文件的路径    1)如果从VS中运行,文件在工程的根目录   2)单独跑exe,那么文件会生成在exe的同级目录中
    //// D:\CPP\Week2\Day1\Info.txt 绝对路径当工程换了路径之后可能会出问题,推荐只写文件名
    //// 
    //// 默认值 是 out  不保留原来文件中的内容
    //// app 表示 append 追加
    // Out.open("Info.txt", ios_base::out | ios_base::binary);
    //
    //FStudent Student{ 10010, "张三", 185.f };

    //// 结构体的保存   
    //    // 1)明文  结构体不能直接保存  按照一定的顺序保存结构体中的属性(成员)
    //// Out << Student.ID << " " << Student.Name << " " << Student.Height << endl;
    //    // 2)密文  二进制的方式去写入结构体(打开文件看不懂)
    //        // 打开文件时需要告诉系统按照二进制的方式打开 ios_base::out | ios_base::binary
    //        // write((char*)&Var, sizeof(Var))
    //Out.write((char*)&Student, sizeof(Student));

    //Out.close();

#pragma region 文件写复习
    //Students[0] = { 10010, "张三", true };
    //Students[3] = { 10011, "李四", true };

    //cout << "输入需要保存的文件名:";
    //string FileName;
    //cin >> FileName;
    //SaveFile(FileName); // SaveFile("Info.txt");
#pragma endregion

#pragma region 文件读
//    // 包含头文件  定义变量   打开文件  读内容  关闭文件
//    ifstream In; // input file stream 
//    In.open("Info.txt");
//    string Str;
//
//#pragma region 不同的读取方式
//   // In >> Str; // 遇到空格自动停止
//   /* while (In >> Str)
//    {
//        cout << Str << endl;
//    }*/
//
//    // getline(In, Str); // 读取一行
//    /*while (getline(In, Str))
//    {
//        cout << Str << endl;
//    }*/
//
//    //// 其他读取方式1
//    //char Content[1024];
//    //while (In >> Content)
//    //{
//    //    cout << Content << endl;
//    //}
//
//    // 其他读取方式2
//    // In.getline()
//    // 第二个参数,读取长度如果设置的不对,读不出来内容,sizeof(变量)
//    /*char Content[1024];
//    while (In.getline(Content, sizeof(Content)))
//    {
//        cout << Content << endl;
//    }*/
//
//    //// 其他读取方式3 一个字符一个字符的读
//    //char C = In.get(); // C默认值一般是先读文件的一个字符
//    //// EOF // 表示End Of File
//    //while (C != EOF)
//    //{
//    //    cout << C;
//    //    C = In.get(); // 读下一个字符,赋值给C
//    //}
//#pragma endregion
//
//    
//
//    In.close();
#pragma endregion

#pragma region 文件读写案例
    // 读写结构体
    //FStudent Student1 = { 10010, "王柳", true };
    //ofstream Out;
    //Out.open("Stu1.txt");
    //Out << Student1.ID << " " << Student1.Name << " " << Student1.bIsMale << endl;
    //Out.close();

    //ifstream In;
    //In.open("Stu1.txt");
    //// 10010 张三 1
    //FStudent Student2;
    //In >> Student2.ID >> Student2.Name >> Student2.bIsMale;
    //In.close();
    //cout << Student2.ID << ":" << Student2.Name << " " << Student2.bIsMale << endl;

    // 读写字符串数组
    //string Names[5]{ "张三", "里斯1", "王 五", "赵六", "朱琪" };
    //ofstream Out;
    //Out.open("Names.txt");
    //for (int i = 0; i < size(Names); ++i)
    //{
    //    Out << Names[i] << endl;
    //}
    //Out.close();

    //string Names1[5]{};
    //ifstream In;
    //In.open("Names.txt");
    //for (int i = 0; i < size(Names1); ++i)
    //{ 
    //    // In >> Names1[i]; // 如果字符串本身带空格,会读乱
    //    getline(In, Names1[i]);
    //}
    //In.close();

    //for (int i = 0; i < size(Names1); ++i)
    //{
    //    cout << Names1[i] << endl;
    //}
    
    // 读写结构体数组
    //Students[0] = { 10010, "张三", true };
    //Students[1] = { 10015, "赵六", false };
    //Students[3] = { 10011, "朱琪", true };
    //ofstream Out;
    //Out.open("Structs.txt");

    //int Count = 0;
    //for (int i = 0; i < size(Students); ++i)
    //{
    //    if (Students[i].ID != 0)
    //    {
    //        Out << Students[i].ID << " " << Students[i].Name << " " << (Students[i].bIsMale ? "男" : "女") << endl;
    //        Count++; // 每成功存一条数据,计数+1
    //    }
    //}
    //Out.close();

    //ifstream In;
    //In.open("Structs.txt");
    //FStudent Students1[10]{};
    ///*for (int i = 0; i < Count; ++i)
    //{
    //    In >> Students1[i].ID >> Students1[i].Name >> Students1[i].bIsMale;
    //}*/

    //// 不知道有多少条数据
    //int Index = 0;
    //string Sex = "";
    //while (In >> Students1[Index].ID >> Students1[Index].Name >> Sex)
    //{
    //    Students1[Index].bIsMale = (Sex == "男" ? true : false);
    //    // Students1[Index].bIsMale = Sex == "男";
    //    Index++; // 每成功读取一条,索引向后偏移一个单位
    //}

    //In.close();


    // 读写数组(存储个数)
    //Students[0] = { 10010, "张三", true };
    //Students[1] = { 10015, "赵六", false };
    //Students[2] = { 10018, "赵六w", false };
    //Students[3] = { 10011, "朱琪", true };
    //ofstream Out;
    //Out.open("Structs.txt");

    //int CountOfValidIndex = 0;
    //// 存文件的时候第一行应该存有效个数
    //for (int i = 0; i < size(Students); ++i)
    //{
    //    if (Students[i].ID != 0)
    //    {
    //        CountOfValidIndex++;
    //    }
    //}
    //Out << CountOfValidIndex << endl;

    //for (int i = 0; i < size(Students); ++i)
    //{
    //    if (Students[i].ID != 0)
    //    {
    //        Out << Students[i].ID << " " << Students[i].Name << " " << (Students[i].bIsMale ? "男" : "女") << endl;
    //    }
    //}
    //Out.close();



    //ifstream In;
    //In.open("Structs.txt");
    //// 首先读取存储的有效个数
    //int Count1 = 0;
    //In >> Count1;
    // 
    //FStudent Students1[10]{};
    //if (Count1 > 0)
    //{
    //    for (int i = 0; i < Count1; ++i)
    //    {
    //        string Str = "";
    //        In >> Students1[i].ID >> Students1[i].Name >> Str;
    //        Students1[i].bIsMale = Str == "男";
    //    }
    //}
    //In.close();



    //cout << "Hello" << endl;

#pragma endregion

#pragma region 二进制文件的读
    //FStudent Student{ 10018, "", false};
    //// Student.Name = "三点水";
    //// 如果结构体中使用了char[],赋值的时候需要使用特殊的形式
    //strcpy_s(Student.Name, "三点水");

    //ofstream Out;
    //Out.open("Student.sav", ios_base::out | ios_base::binary);
    //Out.write((char*)&Student, sizeof(Student));
    //Out.close();

    //ifstream In;
    //In.open("Student.sav", ios_base::in | ios_base::binary);
    //FStudent Student1;
    //In.read((char*)&Student1, sizeof(Student1));
    //In.close();

    // cout << Student1.ID << " " << Student1.Name << " " << Student1.bIsMale << endl;

    


    // 使用二进制进行读写的时候 ,如果有string类型,F5运行会崩溃,推荐使用Ctrl+F5


    // 使用二进制读写保存一个数组
    /*int Nums[]{ 1,2,3,4,5,6 };
    ofstream Out;
    Out.open("Nums.sav", ios_base::out | ios_base::binary);
    Out.write((char*)Nums, sizeof(Nums));
    Out.close();

    ifstream In;
    In.open("Nums.sav", ios_base::in | ios_base::binary);
    int Nums1[6]{};
    In.read((char*)Nums1, sizeof(Nums1));
    In.close();

    for (int i = 0; i < size(Nums1); ++i)
    {
        cout << Nums1[i] << endl;
    }*/

   
#pragma endregion

#pragma region 二进制文件读写案例
    //// 使用二进制读写结构体数组
    //FStudent Students[]{ {10010, "龘龘", true}, {10011, "三点水", false}, {10015, "Lucy", false} };
    //ofstream Out;
    //Out.open("Info.sav", ios_base::out | ios_base::binary);
    //for (int i = 0; i < size(Students); ++i)
    //{
    //    Out.write((char*)&Students[i], sizeof(Students[i]));
    //}
    //Out.close();

    //ifstream In;
    //In.open("Info.sav", ios_base::in | ios_base::binary);
    //FStudent Students1[3]{};
    //for (int i = 0; i < size(Students1); ++i)
    //{
    //    In.read((char*)&Students1[i], sizeof(Students1[i]));
    //}
    //In.close();

    //cout << "Hello" << endl;
#pragma endregion

多文件编程

一般情况下文件是分组 .h  .cpp  Save.h  Save.cpp  有的时候只有.h,没有.cpp
.h中放结构体定义,枚举定义,变量的声明,函数的声明
.cpp中一般放实现文件

Day4

指针

  二级指针

  指针解引用

  值传递解析 : 

  函数指针

  指针基本语法及使用注意点

    int Num = 100;
    int* pNum = &Num;
    cout << sizeof(Num) << " " << Num << endl;
    cout << sizeof(pNum) << " " << pNum << endl;
    // 同一个程序中的同一个变量,在每次启动的时候,地址99.99%是不一样的
    // 同一个程序,同一次启动未关闭之前,同一个变量的内存地址是一样
    // 同一个程序的同一个变量,在不同的机器上内存地址也是不一样的
    // 存储变量的时候,不能存储地址,存储的值(???SaveGame类能不能存储对象【Object   Actor   Component】)

    //// 指针类型和原始值的类型需要匹配(严格匹配)
    //char Ch = '9';
    //// pNum = &Ch; 
    //float Num1 = Num;
    //// float* pNum1 = &Num;

    //// 关于指针书写的格式
    //int* pNum1 = &Num; // 推荐第一种格式
    //int *pNum2 = &Num;
    //int * pNum3 = &Num;

    //// 同一个符号可能会有不同的运算  & (按位与    逻辑与   取地址)   *(指针   乘法   解引用) <<  >>  ->运算符重载
    //string Str = "Hello";
    //string* pStr = &Str;
    //cout << Str << " " << pStr << endl;
    //// 在32位系统下string的大小是28个字节,在64位系统下大小40个字节
    //cout << sizeof(Str) << " " << sizeof(pStr) << endl;


    //int Num = 100;
    //int* pNum = &Num;
    //// Num += 100;
    //// 指针可以通过解引用操作对应的值(在指针变量前+*,取到内存对应的值)
    //*pNum = 200;
    //cout << Num << endl;

  无效指针的几种情况

#pragma region 无效指针的几种情况
    // 空指针 nullptr
    //int* pNum = nullptr; // 定义指针变量时不确定是什么默认值的时候直接给空指针
    //if (pNum != nullptr) // 如果pNum不是空指针   if(pNum)
    //{
    //    cout << *pNum << endl;
    //}

    /*string* pStr = nullptr;
    cout << *pStr << endl;*/

    // 现象1、指针如果是Nullptr,直接打印指针没有问题(不同系统可能会有不同的结果),nullptr解引用 百分之百崩溃
    // 结论1、使用指针之前需要先判断是不是空指针,如果是就停止运行,如果不是再继续
    // 
    // 
    // 野指针(使用没有初始化的指针   使用赋值错误的指针   new delete)

    // 使用没有初始化的指针
    //MyStruct MS;
    //cout << MS.pNum << endl; // CCCCCC
    // cout << *MS.pNum << endl;
    
    // 现象1、使用未经初始化的指针,解引用百分之百崩溃
    // 结论1、指针必须初始化,如果没有合适的值,初始化为nullptr

    // 使用赋值错误的指针
    /*int* pTemp = (int*)0x00000066A852F8C4;
    cout << pTemp << endl;
    cout << *pTemp << endl;*/
    // 现象2、指针赋值的时候给一个真实存在的地址,解引用99.99999%会奔溃
    // 结论2、给指针赋值的时候不要直接赋值地址

    // 动态内存分配  new delete

    // 在堆区开辟4个字节的空间,存储100,然后把这块空间的首地址给到pNum
    // 使用注意点  new 和 delete必须成对出现    delete之后指针置空


    // 现象3、delete之后再去使用指针会出现奇怪的现象(可能会无效,可能会崩溃)
    // 揭露3、delete之后指针必须立刻置空
    //int* pNum = new int(100);
    //string* pStr = new string("火星时代");

    //

    //delete pNum; // 告诉系统,申请4个字节的空间可以回收
    //pNum = nullptr;
    //delete pStr; //
    //pStr = nullptr;

    //if (pStr != nullptr)
    //{
    //    cout << *pStr << endl;
    //}

#pragma endregion

  指针使用规范

#pragma region 指针使用规范
    // 使用指针之前需要先判断是不是空指针,如果是就停止运行,如果不是再继续
    // 指针必须初始化,如果没有合适的值,初始化为nullptr
    // 给指针赋值的时候不要直接赋值地址
    // delete之后指针必须立刻置空

    // 指针使用规范1、指针在使用之前必须赋值(不确定可以赋值nullptr),必须判断是否为空指针
    // 指针使用规范2、new和delete必须成对出现,delete之后指针必须立刻置空


    // 没有new直接delete
    /*int Num = 100;
    int* pNum = &Num;
    delete pNum;
    pNum = nullptr;*/

    // new 和 delete不是成对出现  
    /*int* pNum = new int(50);
    delete pNum;
    pNum = nullptr;*/
    // delete pNum;


    // nullptr NULL // 在Cpp程序中使用nullptr,不要使用NULL
    // new/delete   malloc free  // 在Cpp程序中使用前者,不要使用后者

    
#pragma endregion

  指针作为函数参数

#pragma region 指针作为函数参数
    //int WNum1 = 10;
    //int WNum2 = 50;
    //// 写法2(简单推荐)
    //// pNum1 = &WNum1 // 把实参的地址传递给形参,函数体中直接使用实参的地址
    //Swap(&WNum1, &WNum2);
    //cout << WNum1 << " " << WNum2 << endl;

    /*string Str1 = "Hello";
    string Str2 = "World";
    Swap(&Str1, &Str2);
    cout << Str1 << " " << Str2 << endl;*/



#pragma endregion

  指针作为函数返回值

#pragma region 指针作为函数返回值
    /*string* pTemp = AppendStr1();
    cout << *pTemp << endl;
    delete pTemp;
    pTemp = nullptr;*/
    /*string Str = "火星时代";
    string Str1 = AppendStr1(Str);
    cout << Str1 << endl;*/

    // 函数返回值是指针,不允许返回局部变量
#pragma endregion

  指针作为全局变量的注意点

#pragma region 指针作为全局变量的注意点
    // 如果指针变量是一个全局变量,禁止在某一个时间段指向局部变量(局部变量销毁后,全局变量可能存在不确定行)
    /*pStr = new string("World");
    cout << "函数外部" << pStr << endl;
    cout << *pStr << endl;
    Test();
    cout << "函数外部" << pStr << endl;
    cout << *pStr << endl;*/
#pragma endregion

  结构体指针

#pragma region 结构体指针
    // 结构体指针的基本使用
    /*FStudent Stu1{ "张三", 10010 };
    TestStudent(&Stu1);
    cout << Stu1.ID << endl;*/
    //FStudent* pStu1 = &Stu1;
    //// -> 指针类型(结构体或者类)访问成员特殊符号
    //cout << pStu1->Name << " " << pStu1->ID << endl;

    // 结构体作为函数参数,在函数体内部更改,不会影响外面,如果外面想要受影响需要使用指针类型
   
    
    // 结构体中包含指针类型
    //int Num = 100;
    //FStudent Stu1{ "张三", 10010, &Num};
    //cout << Stu1.pID << endl;
    //cout << *Stu1.pID << endl;

    //FStudent* pStu1 = &Stu1;
    //cout << *(pStu1->pID) << endl; // 第一种写法 指针结构体通过->访问成员
    //cout << *(*pStu1).pID << endl; // 第二种写法  通过解引用把结构体指针变成结构体,再通过.访问成员,因为成员是指针类型,所以需要解引用货值值
    

    // 结构体计算大小
    cout << sizeof(MyStruct2)<< endl;

    // 1、结构体空间不够的时候按照多少申请新的空间(所有基础属性中占用最大的)
    // 2、当空间够用的时候先不申请,不够存储新属性的时候再申请
    // 3、同一种类型(包含数组)可以进行空间挤压
    // 4、如果结构体中有string类型,不是按照40去申请  按照8申请 

    // 推荐   无论是不是数组,想同类型写一起
#pragma endregion

Day5

指针数组补充

数组补充(内存结构和数组名解析)

#pragma region 数组补充(内存结构和数组名解析)
    //int Nums[]{ 1,2,3,4,5,6 };
    // cout << Nums << endl; // 数组名是一个内存地址

    // 结论1 数组名是一个内存地址,指向索引为0的元素
    // 数组 一开始定义的时候需要知道整个的空间的大小(个数),数组不能删除和增加(一整块内存)
    // 数组通过索引访问 Nums[4] =    数组名 + 4 * 索引   数组访问越界(越界的地址可能不属于你的程序)

    //for (int i = 0; i < size(Nums); ++i)
    //{
    //    cout << &Nums[i] << " ";
    //}

     // TestArray(Nums);

    // 结论  普通类型的数组当成函数参数传递的时候,地址传递 
    // 结论  数组作为函数参数的时候本质上就是一个指针  int Nums[]    和  int* Nums 不构成重载,因为本质上都是int*

    /*int* pNums = Nums;*/
    // 指针支持 ++ -- = += -= 
    //cout <<  &Nums[2] << " " << pNums + 2 << endl; // 地址
    //cout << *(pNums + 2) << endl; // 值
    // 
    // 
    //pNums--; // 指针向前偏移
    //cout << Nums << " " << pNums << endl; // Nums的地址会比后面的地址大4个字节
    //cout << *pNums << endl; // 垃圾值,相当于数组向前偏移4个字节,这块内存不一定属于程序,所以是个垃圾值

    // 如果用指针存储数组,对数组进行 加法和减法的运算,运算数就是索引
    /*pNums += 5;
    pNums--;
    cout << *pNums << endl;*/

    /*for (int i = 0; i < size(Nums); ++i)
    {
        cout << *(pNums + i) << endl;
    }*/
    
    
    cout << endl;
#pragma endregion

指针数组

#pragma region 指针数组
	// 数组指针指的是  数组中的元素是指针
	//int Nums[]{ 1, 2, 3 };
	//int Num = 50;
	//int* pNums[2]{Nums, &Num};
	//// 
	//cout << *pNums[0] << endl;
	//cout << *pNums[1] << endl;
	//cout << pNums[0][1] << endl; // Nums[1]
	// 指针数组本质上是一个普通类型的二维数组

	//// 不规则二维数组
	/*int Nums0[]{ 10, 20 };
	int Nums1[]{ 100 };
	int Nums2[]{ 1000, 2000, 3000 };
	int Nums3[]{ 10000,20000,30000,40000 };
	int Nums4[]{ 100000,200000 };

	int* Nums[]{ Nums0, Nums1, Nums2, Nums3, Nums4 };*/

	
	//size 只能判断数组 , 不能判断指针
	// 指针数组能判断size , 但是指针不行
	
	// 单独存储每一行有几个元素
	/*int Lengths[]{ size(Nums0), size(Nums1) , size(Nums2) ,size(Nums3) ,size(Nums4) };
	for (int i = 0; i < size(Nums); ++i)
	{
		for (int j = 0; j < Lengths[i]; ++j)
	    {
	        cout << Nums[i][j] << ",";
	    }
	    cout << endl;*/
	}
#pragma endregion

半动态数组

#pragma region 半动态数组

	// 数组长度不能是变量,需要是一个常量
	/*const int Length = 10;
	int Nums[Length]{};*/

	//// 数组的new和delete
	//int Length = 10;
	//int* Nums = new int[Length] {};

	//delete[] Nums;
	//Nums = nullptr;

	// 从命令行输入一个数决定数组的长度
	// 挨个输入数组中每个元素的值
	// 打印数组中的值
	/*cout << "请输入数组元素的个数:";
	int Count = 0;
	cin >> Count;
	if (Count > 0)
	{
		int* Nums = new int[Count] {};
		for (int i = 0; i < Count; ++i)
		{
			cout << "请输入第" << (i + 1) << "个元素的值:";
			cin >> Nums[i];
		}

		for (int i = 0; i < Count; i++)
		{
			cout << Nums[i] << " ";
		}

		delete[] Nums;
		Nums = nullptr;
	}*/


	//// 模拟半动态数组
	//int Count1 = 3;
	//int* Nums = new int[Count1] {};
	//for (int i = 0; i < Count1; ++i)
	//{
	//    Nums[i] = i * 10;
	//}

	//int* Nums2 = new int[6]{};
	//// Nums2 = Nums; // 只是赋值地址,等NUms销毁后,Nums2会有问题
	//// 将原来数组的值挨个拷贝过来
	//for (int i = 0; i < Count1; ++i)
	//{
	//    Nums2[i] = Nums[i];
	//}

	//// 删除原来的数组的内存
	//delete[] Nums;
	//Nums = nullptr;

	//// 继续赋值剩下的部分(Count1 - 1, 6)
	//for (int i = Count1; i < 6; ++i)
	//{
	//    Nums2[i] = i * 100;
	//}

	//// 打印新数组的值
	//for (int i = 0; i < 6; ++i)
	//{
	//    cout << Nums2[i] << " ";
	//}

	//delete[] Nums2;
	//Nums2 = nullptr;






#pragma endregion

函数指针

int Add(int Num1, int Num2) { return Num1 + Num2; }
int Subtract(int Num1, int Num2) { return Num1 - Num2; }
int Multiply(int Num1, int Num2) { return Num1 * Num2; }
int Divide(int Num1, int Num2) { return Num1 / Num2; }
int Addd(int Num1, int Num2) {
	return Num1 += Num2;
}
//事件分发器用了类似概念
int Add() { return 50; }

// pCalc两个数做运算的函数
int TestCalc(int Num1, int Num2, int (*pCalc)(int, int))
{
	return pCalc(Num1, Num2);
}
int TestCalc1(int Num1, int Num2, int (*pCalc1)(int, int)) {
	return pCalc1(Num1, Num2);
}
//声明
#pragma region 函数指针
	// 函数指针   指向函数的指针

	// auto 会根据变量的值(10)自动推导出变量的类型
	// 用在  1)不知道类型的地方    2)类型名特别长的地方
	 //auto Num = Add; // int(*)(int, int)
	//auto Num = 10;
	// 结论  函数名就是一个函数指针,指向自己

	// 写函数指针的步骤      函数声明拿过来 去掉;    将函数名替换成 (*VarName)  去掉形参名字
	// int (*pAdd)() = Add; // = 后面是函数名,不要写成函数调用


	// 函数指针的调用
	/*cout << pAdd() << endl;
	cout << pAdd1(10, 100) << endl;*/
	// void (*pVoid)()
	// pAdd = TestVoid; // 函数指针赋值的时候需要函数签名完全一致

	/*int (*pAdd1)(int, int) = Add;
	cout << pAdd1(10, 100) << endl;
	pAdd1 = Multiply;
	cout << pAdd1(10, 100) << endl;*/

	//cout << TestCalc(100, 500, Add) << endl;
	//cout << TestCalc(100, 500, Subtract) << endl;
	//cout << TestCalc(100, 500, Multiply) << endl;
	//cout << TestCalc(100, 500, Divide) << endl;

cout << TestCalc1(1, 2, Addd);



#pragma endregion

 

posted @ 2024-03-04 18:12  啊賢  阅读(7)  评论(0编辑  收藏  举报