C++基础篇(2)

news2024/9/23 7:26:07

目录

前言

1.缺省参数

2.函数重载

 2.1函数重载的基本规则

​编辑2.2注意事项

2.3 重载解析(Overload Resolution)--补充内容

3.引用

3.1引用的概念和定义

3.2引用的特性

3.3引用的使用

3.4const引用

4.指针和引用的关系

结束语

前言

上节小编讲解了命名空间和函数的输入输出,本节将讲解缺省参数,函数重载等知识。

1.缺省参数

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参,则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)
全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左
依次连续缺省,不能间隔跳跃给缺省值。
例如(错误示范)
void func(int a, double b = 3.14, const char* c = "default") { // 正确
    // 函数体
}

void func(int a = 1, double b, const char* c = "default") { // 错误,不能跳过 b
    // 函数体
}
#include <iostream>
using namespace std;
void func(int x=0) {
	cout << x << endl;
}
int main() {
// 没有传参时,使⽤参数的默认值
// 传参时,使⽤指定的实参
	func();
	func(10);
	return 0;
}

运行结果:

0

10

带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参。
#include <iostream>
using namespace std;
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}
int main()
{
	Func1();
	Func1(1);
	Func1(1, 2);
	Func1(1, 2, 3);
	Func2(100);
	Func2(100, 200);
	Func2(100, 200, 300);
    Func2(100, ,300);//错误
	return 0;
}

03e0f99269104ad9857a995b841d7c85.png

函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省
值。
// 在头文件中的函数声明
void func(int a = 1, double b = 3.14, const char* c = "default");

// 在源文件中的函数定义
void func(int a, double b, const char* c) {
    // 函数体
}

2.函数重载

在C++中,函数重载(Function Overloading)是指在同一作用域内可以存在多个同名函数,但这些函数的参数列表(参数的个数、类型或者顺序)必须不同。编译器会根据传递给函数的参数来决定调用哪一个重载版本。

 2.1函数重载的基本规则
 

1.参数数量不同:函数可以具有不同数量的参数。

#include <iostream>
using namespace std;
int Add(int a, int b) {
	return a + b;
}

int Add(int a, int b, int c) { 
	return a + b + c;
}

int main() {
	int sum1 = Add(10, 20);   
	double sum2 = Add(10,20,30); 

	cout << "sum1: " << sum1 << endl;
	cout << "sum2: " << sum2 << endl;
	return 0;
}

7a6272792b2f45329a1ae531db18f8ee.png
2. 参数类型不同:函数可以具有不同类型的参数。

#include <iostream>
using namespace std;
int add(int a, int b) {
	cout << "int add(int a, int b)"<<endl;
		return a + b;

}
double add(double a, double b) {
	cout << "double add(double a, double b)"<<endl;
		return a + b;

}
int main() {
	int sum1 = add(10, 20);   
	double sum2 = add(1.5, 2.5); 

	cout << "sum1: " << sum1 << endl;
	cout << "sum2: " << sum2 << endl;
	return 0;
}

f1f6cddca9174c738581aee06c9f704e.png
3. 参数顺序不同:如果参数类型相同,但顺序不同,也可以构成重载。

#include <iostream>
using namespace std;
void f(int a, char b)
{
	cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
	cout << "f(char b, int a)" << endl;
}
int main() {
	f(10, 'c');
	f('c', 10);
	return 0;
}

668ff08bb9574e458d0164b9479f4544.png

2.2注意事项

- 返回类型:函数重载与返回类型无关,即不能仅通过改变返回类型来重载函数。
-默认参数:使用默认参数的函数可能会导致重载解析的歧义,应当小心使用。

int Add(int a, int b) {
    return a + b;
}

double Add(int a, int b) { // 错误:不能仅通过返回类型来重载
    return static_cast<double>(a + b);
}
#include <iostream>
using namespace std;

// 下⾯两个函数构成重载
// f()但是调⽤时,会报错,存在歧义,编译器不知道调⽤谁
void f()
{
	cout << "f()" << endl;
}
void f(int a = 10)
{
	cout << "f(int a)" << endl;
}
int main() {
	f();
	return 0;
}

fd43ff7a5a1a4f20832734c981822d9e.png

2.3 重载解析(Overload Resolution)--补充内容

当调用一个重载函数时,编译器会根据提供的实参和每个重载函数的形参列表进行匹配,以确定调用哪一个函数。这个过程称为重载解析。如果编译器无法明确地确定应该调用哪个函数,或者找到多个合适的匹配,就会产生编译错误。

函数重载是C++多态性的一种形式,它允许程序员使用相同的名字来执行相似的操作,这增强了代码的清晰性和可读性。

3.引用

3.1引用的概念和定义

在 C++ 中,引用是一个变量的别名。一旦一个引用被初始化为指向一个对象,它就不能被重新绑定到另一个对象。这与指针不同,指针可以在任何时候指向不同的对象。

引用的概念

  • 别名:引用为另一个变量提供了一个额外的名字,它和原变量指向相同的内存位置。
  • 不可变性:一旦引用被初始化,它就不能被重新赋值为另一个变量的引用。
  • 无需解引用:使用引用时,不需要像指针一样使用 * 操作符来访问引用的值。
  • 效率:引用在传递参数时可以避免不必要的复制,特别是对于大型对象来说,使用引用可以提高效率。

引用的定义

引用在 C++ 中是这样定义的:

类型 &引用名 = 原变量名;

一些有趣的实例:

比如:水浒传中李逵,宋江叫"铁牛",江湖上人称"黑旋风";林冲,外号豹子头;

这里,类型 是原变量的类型,& 符号用于声明引用,引用名 是你给引用起的名字,而 原变量名 是已经存在的变量。

1f4ad6d33e3f44d49138ef72580f55b2.png

#include <iostream>
using namespace std;
int main() {
	int a = 520;
	int& b = a;
	int& c = a;
	int& d = b;
	++d;
// 引⽤:b和c是a的别名
	cout << &a << endl;
	cout << &b << endl;
	cout << &c << endl;
// 也可以给别名b取别名,d相当于还是a的别名
	cout << &d << endl;
//地址,值都是一样的
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << d << endl;
	return 0;
}

e4fe0f1e22424434810ab50ad72d01dc.png

3.2引用的特性

• 引用在定义时必须初始化
• 一个变量可以有多个引用
• 引用一旦引用一个实体,再不能引用其他实体
#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	// 编译报错:“ra”: 必须初始化引⽤
	//int& ra;
	int& b = a;
	int c = 20;
	// 这⾥并⾮让b引⽤c,因为C++引⽤不能改变指向,
	// 这⾥是⼀个赋值
	b = c;
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	b = 30;
	cout << &a << endl;
	cout << &b << endl;
	cout << &c << endl;
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	return 0;
}

c4480a75ea4b458eb7c23cc2e3926981.png

3.3引用的使用

1.引用在实践中主要是于引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被引用对象。
2.引用传参跟指针传参功能是类似的,引用传参相对更方便一些。
3.引用返回值的场景相对比较复杂,小编实力有限,以后等知识丰富了再会详细讲解。
4.引用和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。C++的引用跟其他语言的引用(如Java)是有很大的区别的,除了用法,最大的点,C++引用定义后不能改变指向,java的引用可以改变指向。
5.一些主要用C代码实现版本数据结构教材中,使用C++引用替代指针传参,用的是简化程序,避开复杂的指针。
代码实例:
#include <iostream>
using namespace std;
void Swap(int& x, int& y) {
	int temp = x;
	x = y;
	y = temp;
}
int main() {
	int x = 520, y = 1314;
	cout << x << " " << y << endl;
	Swap(x, y);
	cout << x << " " << y << endl;

	return 0;
}

816ca5a6fbd5403c9824d39573ac5af3.png

#include<iostream>
#include <assert.h>
#include <stdlib.h> 

using namespace std;
typedef int STDataType;
typedef struct Stack {
    STDataType* a;
    int top;
    int capacity;
} ST;

void STInit(ST& rs, int n = 4) {
    rs.a = (STDataType*)malloc(n * sizeof(STDataType));
    rs.top = 0; // 栈顶初始化为 0,表示栈为空
    rs.capacity = n;
}

void STPush(ST& rs, STDataType x) {
    // 满了,扩容
    if (rs.top == rs.capacity) {
        printf("扩容\n");
        int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;
        STDataType* tmp = (STDataType*)realloc(rs.a, newcapacity * sizeof(STDataType));
        if (tmp == NULL) {
            perror("realloc fail");
            return;
        }
        rs.a = tmp;
        rs.capacity = newcapacity;
    }
    rs.a[rs.top] = x; 
    rs.top++; // 栈顶指针上移
}

int& STTop(ST& rs) {
    assert(rs.top > 0); // 确保栈不为空
    return rs.a[rs.top - 1]; // 返回栈顶元素的引用
}

int main() {
    ST st1;
    STInit(st1);
    STPush(st1, 1);
    STPush(st1, 2);
    cout << STTop(st1) << endl; // 输出栈顶元素 2
    STTop(st1) += 10; // 通过引用修改栈顶元素
    cout << STTop(st1) << endl; // 输出修改后的栈顶元素 12
    return 0;
}

bc232eec8078412581694a024397c8b1.png

3.4const引用

在 C++ 中,const 引用是一种特殊类型的引用,它被用来引用一个对象,同时保证这个引用不会修改所引用的对象。这种引用通常用于函数参数,以允许函数读取传递的对象,但不允许通过引用修改它。

以下是 const 引用的几个关键点:

声明 const 引用

const 类型 &引用名 = 引用的对象;

这里,类型 是被引用对象的类型,引用名 是你给引用起的名字,而 引用的对象 是你想要引用的实际对象。

使用 const 引用的好处

  • 保护数据不被修改:通过 const 引用,你可以确保传递给函数的参数不会被函数修改。
  • 可以引用临时对象和字面量const 引用可以引用右值(如字面量或临时对象),这是非 const 引用无法做到的。
  • 可以与任何类型的对象兼容:只要类型可以转换为 const 引用的类型,就可以创建 const 引用。

示例

不需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样一些场景下a*3的和结果保存在一个临时对象中, int& rd = d 也是类似,在类型转换中会产生临时对象存储中间值,也就是时,rb和rd引用的都是临时对象,而C++规定临时对象具有常性,所以这里就触发了权限放大,必须要用常引用才可以。
int main()
{
const int a = 10;
// 编译报错:error C2440: “初始化”: ⽆法从“const int”转换为“int &”
// 这⾥的引⽤是对a访问权限的放⼤
//int& ra = a;
// 这样才可以
const int& ra = a;
// 编译报错:error C3892: “ra”: 不能给常量赋值
//ra++;
// 这⾥的引⽤是对b访问权限的缩⼩
int b = 20;
const int& rb = b;
// 编译报错:error C3892: “rb”: 不能给常量赋值
//rb++;
return 0;
}
#include<iostream>
using namespace std;
int main()
{
int a = 10;
const int& ra = 30;
// 编译报错: “初始化”: ⽆法从“int”转换为“int &”
// int& rb = a * 3;
const int& rb = a*3;
double d = 12.34;
// 编译报错:“初始化”: ⽆法从“double”转换为“int &”
// int& rd = d;
const int& rd = d;
return 0;
}

#include <iostream>
using namespace std;

void print(const int& x) {
    cout << x << endl;
    // x = 5; // 错误:不能通过 const 引用修改对象
}

int main() {
    int a = 10;
    const int& ref = a; // 创建一个对 a 的 const 引用
    // ref = 20; // 错误:不能通过 const 引用修改对象

    print(a); // 正确:传递 int
    print(20); // 正确:传递字面量,通过 const 引用允许

    return 0;
}

注释前的错误:

c0263619b1d34b908ea737dbd566f98b.png

正确运行结果:

dd74ed8c39d14563875c87faf1f56ec2.png

注意事项

  • 一旦 const 引用被初始化,它就不能再引用其他对象。
  • const 引用不能引用非 const 对象的地址,如果需要引用非 const 对象,必须显式地声明非 const 引用。

总之,const 引用在 C++ 中是一种非常有用的特性,它不仅提供了对数据的保护,还增加了代码的灵活性和安全性。

4.指针和引用的关系

C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,能有重叠性,但是各有自己的特点,互相不可替代。
• 语法概念上引用是一个变量的取别名不开空间,指针是存储一个变量地址,要开空间。
• 引用在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
• 引用在初始化时引用一个对象后,就不能再引用其他对象;而指针可以在不断地改变指向对象。
• 引用可以直接访问指向对象,指针需要解引用才是访问指向对象。
• sizeof中含义不同,引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位下是8byte)
• 指针很容易出现空指针和野指针的问题,引用很少出现,引用使用起来相对更安全一些。

结束语

本篇博客也就到此结束啦,C++ 的入门也差不多了,下个阶段我们将步入类和对象的学习!!!
最后支持小编的友友和大佬们点个赞吧,也欢迎大家在评论区多多交流,感谢大家的支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1930004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

互联网末法时代的一些思考

这篇文章也是临时起意&#xff0c;很长一段时间没写个人思考类的文章&#xff0c;主要原因也是时间完全不够用。随着年龄的增长&#xff0c;看待问题的视角也逐渐发生变化&#xff0c;例如从关注现象到关注动机&#xff0c;从关注结果到关注起因&#xff0c;2021年的时代我曾经…

前端设计模式:教科书般的实践指南

前端设计模式&#xff1a;教科书般的实践指南 引言 亲爱的前端小伙伴们&#xff0c;你们是否曾经在代码的海洋中迷失方向&#xff1f;是否曾经被项目经理的"简单需求"折磨得欲仙欲死&#xff1f;别担心&#xff0c;今天我们就来聊聊那些能让你在前端江湖中纵横捭阖…

Qt程序图标更改以及程序打包

Qt程序图标更改以及程序打包 1 windows1.1 cmake1.1.1 修改.exe程序图标1.1.2 修改显示页面左上角图标 1.2 qmake1.2.1 修改.exe程序图标1.2.2 修改显示页面左上角图标 2 程序打包2.1 MinGW2.2 Visual Studio 3 参考链接 QT6 6.7.2 1 windows 1.1 cmake 1.1.1 修改.exe程序图…

新书速览|深入理解Hive:从基础到高阶:视频教学版

《深入理解Hive&#xff1a;从基础到高阶&#xff1a;视频教学版》 本书内容 《深入理解Hive:从基础到高阶:视频教学版》采用“理论实战”的形式编写&#xff0c;通过大量的实例&#xff0c;结合作者多年一线开发实战经验&#xff0c;全面地介绍Hive的使用方法。《深入理解Hiv…

昂科烧录器支持Hynetek慧能泰半导体的三端口控制器HUSB366

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中Hynetek慧能泰半导体的三端口控制器HUSB366已经被昂科的通用烧录平台AP8000所支持。 HUSB366是一款高性能、高集成度的双USB Type-C和一个USB Type-A三端口控制器&#xff0c;…

如何将电子书发送到kindle

修改guide Amazon之kindle 修改邮箱 参考&#xff1a; blog 多种方式&#xff1a;如何将电子书发送到kindle

不用ps?AI生成免抠素材,让你的工作效率翻倍!

在当今的工作和创作中&#xff0c;免抠素材的重要性日益凸显。无论是制作精美的 PPT &#xff0c;还是设计个性化的电子手账&#xff0c;优质的免抠素材都能起到画龙点睛的作用。然而&#xff0c;寻找合适的免抠素材并非易事&#xff0c;很多时候我们会面临各种困扰。 有不少朋…

PHP webshell 免杀方法

本文介绍php类webshell简单的免杀方法&#xff0c;总结不一定全面&#xff0c;仅供读者参考。 webshell通常可分为一句话木马&#xff0c;小马&#xff0c;大马&#xff0c;内存马。 一句话木马是最简单也是最常见的webshell形式&#xff0c;这种木马体积小&#xff0c;隐蔽较…

大厂必争之地!AI搜索产品万字长文分析

多年以前&#xff0c;百度、谷歌等就在开始做智能搜索&#xff0c;但彼时的智能搜索只是对搜索结果的简单整理归纳&#xff0c;效果并不如人意。当前AI爆火&#xff0c;在AI的加持下&#xff0c;搜索会不会更强大一些呢&#xff1f;其实并不是&#xff0c;至少当前AI搜索的使用…

MyBatis源码中的设计模式2

组合模式的应用 组合模式介绍 组合模式(Composite Pattern) 的定义是&#xff1a;将对象组合成树形结构以表示整体和部分的层次结构。组合模式可以让用户统一对待单个对象和对象的组合。 比如&#xff1a;Windows操作系统中的目录结构&#xff0c;通过tree命令实现树形结构展…

安装 MySQL,修改用户名、放通外部机器访问

Hello&#xff0c;好记性不如烂笔头~ 虽说不会经常部署 MySQL &#xff08; OS&#xff1a;当然了&#xff0c;这服务不是公司部署好等着用就好了吗~&#xff1f;&#xff09; 但&#xff01;作为程序员、能够随手、无卡顿的部署并使用一个新的数据库 / 数据库集群也算是基操了…

【Blockly图形化积木编程二次开发学习笔记】1.工具箱的实现

文章目录 Blockly 版本选择上手 Blockly 版本选择 在【兰州大学】Blockly创意趣味编程【全36讲】主讲教师&#xff1a;崔向平 周庆国中提到&#xff0c;在18年6月份之前的版本中&#xff0c;可以通过安装依赖库的方式&#xff0c;打开开发者工具的离线版本&#xff0c;但是新版…

AWS CDN新增用户ip 地区 城市 响应头

1.需要自定义cdn缓存策略 这里的策略也是先复制之前的cdn策略哈 最后复制完了 全部新增这两条标头key CloudFront-Viewer-Country CloudFront-Viewer-City 2.然后新增cdn函数&#xff0c;应用你写的这个函数 function handler(event) {var request event.request;var respon…

Raw Socket(二)循环队列收发数据

完整代码在&#xff1a; 添加链接描述 其中tcp_handshake文件夹是实现TCP三次握手的demo。 完整代码参考&#xff1a; https://github.com/praveenkmurthy/Raw-Sockets 代码实现基于raw socket的TCP协议&#xff0c;发送http请求包并接收回包&#xff0c;…

JAVA中的Prim和Dijkstra问题详解

1.概念 Prim算法是一种计算加权无向图的最小生成树的算法。所谓最小生成树&#xff0c;是指一个图的子图&#xff0c;它包含图中所有的顶点&#xff0c;并且有保持图连通的最少的边&#xff0c;且所有边的权值之和最小。Prim算法的基本思想是从图中任意一个顶点开始&#xff0…

Go Web开发框架之Gin

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

【香橙派AiPro】基于VGG16的火灾检测模型预测

目录 引言开发板介绍开发板使用准备工作工具文档 拨码开关镜像烧录连接开发板下载MobaXterm网线-SSH连接开发板设置WIFI连接WIFI-SSH连接开发板确定开发板IP方法 Vnc可视化WindowsiPad 开发工具安装 散热风扇基于VGG16的火灾检测模型预测数据集准备目录结构代码操作 安装宝塔最…

pico+unity手柄和摄像机控制初级设置

1、摄像头配置 摄像头模式、floor是追踪原点类型&#xff08;将根据设备检测到地面的高度来计算追踪原点&#xff09;&#xff0c; Device 模式时&#xff0c;为通常理解的 Eye 模式&#xff0c;不会将根据设备检测到地面的高度来计算追踪原点 选择floor时&#xff0c;修改相…

UE4-初见虚幻引擎

一.创建自己的工程 1.启动 a.通过桌面双击图标来打开对应版本的虚幻引擎 b.通过EPIC启动器开启动虚幻引擎 2.选择或新建项目 ps:高版本虚幻编辑器可以打开低版本的虚幻项目&#xff0c;但是高版本虚幻的项目不可以由低版本的虚幻编辑器打开。 3. 选择要打开的项目 4.选择模版 选…

Linux桌面环境手动编译安装librime、librime-lua以及ibus-rime,提升中文输入法体验

Linux上的输入法有很多&#xff0c;大体都使用了Fcitx或者iBus作为输入法的引擎。相当于有了一个很不错的“地基”&#xff0c;你可以在这个“地基”上盖上自己的“小别墅”。而rime输入法&#xff0c;就是一个“毛坯别墅”&#xff0c;你可以在rime的基础上&#xff0c;再装修…