当前位置: 首页 > news >正文

C++工程实战入门笔记5-函数(二)

函数默认参数

//默认参数
void TestFuncDec(int x, int y = 200, int z = 300)
{cout << "TestFuncDec: " << x << "," << y << "," << z << endl;
}int main()
{TestFuncDec(100);TestFuncDec(100, 100);TestFuncDec(100, 100, 100);system("pause");
}

在这里插入图片描述

函数重载

//函数重载,函数同名,参数不同类型或者不同数量
void Test(int p)
{cout << "Test:" << p << endl;
}
void TestOverLoad(int x)
{cout << "int:" << x << endl;Test(x);
}
void TestOverLoad(float x)
{cout << "float:" << x << endl;if (x - (int)x > 0.5)x++;Test(x);
}
void TestOverLoad(double x,double y)
{cout << "double x y:" << x <<","<<y<< endl;Test(x+y);
}
int main()
{TestOverLoad(100);cout << endl;TestOverLoad(1.3f);cout << endl;TestOverLoad(1.6f);cout << endl;TestOverLoad(1.7, 2.3);cout << endl;system("pause");
}

在这里插入图片描述
使用默认参数:

    函数基本行为相同,只是某些参数通常使用特定值希望保持代码简洁,减少函数数量参数有自然的默认值

使用函数重载:

    不同参数组合需要完全不同的实现参数类型不同导致处理逻辑不同需要处理不同的参数数量且逻辑差异大

函数与数组和字符串

在这里插入图片描述

int main()
{char arr[10];//声明一个可以容纳10个字符的数组,但未初始化,内容是不确定的char str1[]{ "0123456789" };//包含11个字符的数组,编译器自动推导数组大小为11(10个字符 + 1个空终止符)const char* str2{ "ABCDE" };//指向常量字符的指针,使用const修饰符以确保不会意外修改字符串内容int datas[]{ 0,1,2,3,4,5,6,7,8 };//包含9个整数的数组,编译器自动推导数组大小为9cout << "arr:" << sizeof(arr) << '\t'<< "str1:" << sizeof(str1) << '\t'<< "str2:" << sizeof(str2) << '\t'<< "datas:" << sizeof(datas) << endl;//arr:10  str1:11 str2:8  datas:36//数组可以auto遍历,指针不可以for (auto d : datas){cout << d << '\t';}cout<< endl;//更改无效,d只是数组中元素的复制for (auto d : datas) d += 100;for (auto d : datas) cout << d << '\t';cout << endl;//更改有效,引用可以更改数组中元素值for (auto &d : datas) d += 100;for (auto d : datas) cout << d << '\t';cout << endl;system("pause");
}

在这里插入图片描述

返回数组只能是指针,数组参数全部变为指针

int* TestArr(char arr[10], char str1[], const char* str2, int datas[])
{cout << "arr:" << sizeof(arr) << '\t'<< "str1:" << sizeof(str1) << '\t'<< "str2:" << sizeof(str2) << '\t'<< "datas:" << sizeof(datas) << endl;return datas;
}int main()
{char arr[10];//声明一个可以容纳10个字符的数组,但未初始化,内容是不确定的char str1[]{ "0123456789" };//包含11个字符的数组,编译器自动推导数组大小为11(10个字符 + 1个空终止符)const char* str2{ "ABCDE" };//指向常量字符的指针,使用const修饰符以确保不会意外修改字符串内容int datas[]{ 0,1,2,3,4,5,6,7,8 };//包含9个整数的数组,编译器自动推导数组大小为9TestArr(arr, str1, str2, datas);//arr:8   str1:8  str2:8  datas:8system("pause");
}

在这里插入图片描述
也可以把

char arr[10];//声明一个可以容纳10个字符的数组,但未初始化,内容是不确定的
char str1[]{ "0123456789" };//包含11个字符的数组,编译器自动推导数组大小为11(10个字符 + 1个空终止符)
const char* str2{ "ABCDE" };//指向常量字符的指针,使用const修饰符以确保不会意外修改字符串内容
int datas[]{ 0,1,2,3,4,5,6,7,8 };//包含9个整数的数组,编译器自动推导数组大小为9

换成

vector<char> arr(10);
char str1[]{ "0123456789" };
const char* str2{ "ABCDE" };
vector<int> datas{ 0,1,2,3,4,5,6,7,8 };

完整测试vector

vector<int> TestVecStr(vector<char> arr,string str1,string str2, vector<int> datas)
{cout << "arr:" << arr.size() << '\t'<< "str1:" << str1.size() << '\t'<< "str2:" << str1.size() << '\t'<< "datas:" << datas.size() << endl; //.size()不计算\0的大小,只计算字符数量大小for (auto &d : datas) d += 10000;return datas;
}int main()
{vector<char> arr(10);char str1[]{ "0123456789" };const char* str2{ "ABCDE" };vector<int> datas{ 0,1,2,3,4,5,6,7,8 };auto res = TestVecStr(arr, str1, str2, datas);for (auto d : datas) cout<<d<<'\t';//datas内部没改...vector<int> string 不引用指针,会复制堆中数据cout << endl;for(auto d:res) cout << d << '\t';//datas返回值改了cout << endl;system("pause");
}

在这里插入图片描述
下面是怎么能vector不复制堆内容,直接改呢,加入引用

将:

vector<int> TestVecStr(vector<char> arr,string str1,string str2, vector<int> datas)

改成

vector<int> TestVecStr(vector<char> arr,string str1,const string &str2, vector<int> &datas)

完整代码

vector<int> TestVecStr(vector<char> arr,string str1,const string &str2, vector<int> &datas)
{cout << "arr:" << arr.size() << '\t'<< "str1:" << str1.size() << '\t'<< "str2:" << str1.size() << '\t'<< "datas:" << datas.size() << endl; //.size()不计算\0的大小,只计算字符数量大小for (auto &d : datas) d += 10000;return datas;
}int main()
{vector<char> arr(10);char str1[]{ "0123456789" };const char* str2{ "ABCDE" };vector<int> datas{ 0,1,2,3,4,5,6,7,8 };auto res = TestVecStr(arr, str1, str2, datas);for (auto d : datas) cout<<d<<'\t';//datas内部改了,cout << endl;for(auto d:res) cout << d << '\t';//datas返回值改了cout << endl;system("pause");
}

在这里插入图片描述

#pragma once 作用

防止同一个头文件在同一个编译单元中被多次包含,从而避免重复定义、重复声明等编译错误。

核心作用:头文件保护

想象一下这个场景:

  • main.cpp 同时包含了 headerA.h 和 headerB.h
  • 而 headerB.h 本身也包含了 headerA.h
  • 这样一来,headerA.h 的内容在 main.cpp 中被包含了两次

如果没有保护措施,头文件中的函数声明、类定义等就会出现两次,编译器会报“重复定义”的错误。

#pragma once 就是用来解决这个问题的。你只需要在头文件的最开头加上它:

// 在 myheader.h 中
#pragma once // <- 就是这行// 头文件的实际内容
class MyClass {// ...
};
void myFunction();

#pragma once 出现之前,人们使用宏定义守卫来实现同样的功能:

// 传统的宏定义守卫方式
#ifndef MY_UNIQUE_HEADER_NAME_H_ // 如果没有定义这个宏
#define MY_UNIQUE_HEADER_NAME_H_ // 就定义它// 头文件内容...
class MyClass {// ...
};#endif // MY_UNIQUE_HEADER_NAME_H_ // 结束

现代 C++ 开发中,绝大多数情况下推荐使用 #pragma once。
使用 #pragma once 的情况:

你的项目主要使用 Visual Studio、GCC、Clang 等现代编译器(它们全都支持)。
你追求代码简洁和可读性。
你不关心极端的跨编译器可移植性(例如,要移植到一些非常古老的编译器上)。

使用宏定义守卫的情况:

你编写的代码需要在非常古老或冷门的编译器上编译,而这些编译器不支持 #pragma once。
你的头文件可能通过符号链接被以不同路径包含,你需要确保万无一失。

最佳实践

1、现代项目标配:直接在头文件顶部使用 #pragma once。这是当前的主流做法,简洁高效。

#pragma once
// ... 你的头文件内容

2、兼容性要求极高的项目或库:如果你不确定使用者的编译环境,为了最大兼容性,可以使用两者结合的方式。编译器会智能处理,不会带来额外开销。

#pragma once
#ifndef MY_PROJECT_UNIQUE_NAME_H_
#define MY_PROJECT_UNIQUE_NAME_H_
// ... 头文件内容
#endif

多文件声明定义函数和全局变量

头文件(test.h)

#pragma once
//声明全局变量
extern int gcount;
//int gerr; //.h中不能出现定义变量//函数声明
int TestFunc(int index, int x, int y = 10);

cpp文件(test.cpp)

#include "stdafx.h"
#include "test.h"
#include<iostream>
using namespace std;
//全局变量定义
int gcount;
int TestFunc(int index, int x, int y)//在 C++ 中,函数的默认参数只能在函数声明中指定一次,通常在头文件中。在函数定义中再次指定默认参数会导致编译错误。
{cout << index << " " << x << ":" << y << endl;return 0;
}

主函数main

#include<iostream>
#include "test.h"
using namespace std;
int main()
{cout <<"gcount="<< gcount << endl;TestFunc(100, 600, 400);system("pause");
}

在这里插入图片描述

string字符串指针和vector之间的转换

将 const char*字符串 转换为 vector

int main()
{const char* cstr{ "测试const char*到vector" };//复制内容到vector,可以传递//内存开始地址和结束地址//使用加法运算符移动指针//每加1 移动1个类型大小的内容int size = strlen(cstr);//字符串长度,不包含结尾\0//一:数据开始的内存;二:数据最后内存的下一位// \0的下一位vector<unsigned char> data(cstr,cstr+size+1);cout << data.size() << endl;cout << data.data() << endl;system("pause");
}

在这里插入图片描述

将 char数组 转换为 vector

data.clear();
cout << "data.clear()" << endl;
char astr[]{ "测试数组到vector" };
data.assign(astr, &astr[sizeof(astr)]);
cout << data.size() << endl;
cout << data.data() << endl;

在这里插入图片描述

将 string 转换为 vector

string str{ "测试string到vector" };
data.clear();
cout << "data.clear()" << endl;
data.assign(str.begin(), str.end());
data.push_back('\0');
cout << data.size() << endl;
cout << data.data() << endl;

在这里插入图片描述

vector转换成string

//vector转换成string
string outstr(data.begin(), data.end());
cout << "outstr = " << outstr << endl;

在这里插入图片描述

http://www.dtcms.com/a/351536.html

相关文章:

  • React前端开发_Day1
  • 迅为R3588S开发板ADB使用手册-运行shell
  • ctfshow_萌新web16-web20-----文件包含日志注入
  • 运算符(1)
  • 函数默认值的陷阱:用None和Docstring来描述可变默认值的参数 (Effective Python 第24条)
  • Qt 窗口 - 1
  • [Maven 基础课程]IDEA 配置 Maven
  • 基于 W55MH32Q-EVB 实现 FatFs 文件系统+FTP 服务器
  • C++ SNIFE
  • 数据结构——链表(2)——双向链表
  • 【图像处理 - 基础知识】ISP(Image Signal Processor)处理
  • 深度学习之卷积神经网络
  • 组件版本升级 - MySQL_8.4对比MySQL_8.0
  • 用 mem0 构建一个简单的 AI Healthcare 助手
  • 基于Vue通用组件定制化的场景解决
  • UNet改进(35):基于WGAM模块的PyTorch实战
  • Qt在Linux下编译发布 -- linuxdeployqt的使用
  • 第十九节:阴影进阶 - 软阴影与性能平衡技术
  • FileMenu Tools for Win:突破 Windows 文件管理困境的利器
  • Git:基本使用
  • 数字化转型三阶段:从信息化、数字化到数智化的战略进化
  • Leetcode+Java+动态规划II
  • 知行——同为科技24周年庆典
  • Thingsboard 租户管理员权限,增加租户普通用户权限
  • Go errgroup:高效并发控制与错误处理
  • WPF基于LiveCharts2图形库,实现:折线图,柱状图,饼状图
  • 03. 协程入门_Android异步处理机制
  • 系统架构设计师备考第7天——网络协议中间件软件构件
  • WebSocket简单了解
  • 线性代数之深入理解旋转矩阵