【C++】初识C++基础篇·一(命名空间,函数重载,缺省参数,引用);

文章目录

  • 前言
  • 1.输入与输出
    • 输出
    • 输入
      • cin和scanf的对比
  • 2.命名空间
  • 2.1namespace存在的意义
  • 2.2namespace的使用
  • 3.缺省参数
  • 4.函数重载
    • 重载函数的调用规则
  • 5.引用

在这里插入图片描述

前言

我们先通过一段简单的代码来拉开C++的序幕;

//text.cpp
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{printf("hello world");return 0;
}//int main()
//{
//	cout << "hello world" << endl;
//	return 0;
//}

在上述代码中,**printf(“hello world”);所实现的效果。与下面的cout << “hello world” << endl;**的效果相同,我们要知道在C++当中他是兼容C语言的语法的,所以代码中C语言的语法也能运行成功;
而在这里面就涉及到了我们下面要说的在C++中的输入与输出;

1.输入与输出

• < iostream > 是 Input Output Stream 的缩写,是标准的输⼊、输出流库,定义了标准的输⼊、输
出对象。
• std::cin 是 istream 类的对象,它主要⾯向窄字符(narrow characters (of type char))的标准输
⼊流。
• std::cout 是 ostream 类的对象,它主要⾯向窄字符的标准输出流。
• std::endl 是⼀个函数,流插⼊输出时,相当于插⼊⼀个换⾏字符加刷新缓冲区。
<<是流插⼊运算符,>>是流提取运算符。(C语⾔还⽤这两个运算符做位运算左移/右移)
• 使⽤C++输⼊输出更⽅便,不需要像printf/scanf输⼊输出时那样,需要⼿动指定格式, C++的输⼊输出可以⾃动识别变量类型其实最重要的是C++的流能更好的⽀持⾃定义类型对象的输⼊输出。
cout/cin/endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以要通过命名空间的使⽤⽅式去⽤他们
• ⼀般⽇常练习中我们可以using namespace std,实际项⽬开发中不建议using namespace std。
• 这⾥我们没有包含<stdio.h>,也可以使⽤printf和scanf, 因为在 < iostream >中间接包含了。vs系列编译器是这样的,其他编译器可能会报错。

对于输入和输出两种操作来说,最重要的就是流插入运算符和流提取运算符;

输出

输出:cout << “hello world” << endl;
"<<"符号表示的是将该字符串传给cout(传的只是地址),该符号指出了信息流动的方向;而且它不单单可以只传输一段字符串,甚至是多段、不同类型的多次拼接传输。例如:

#include<iostream>
#include<stdio.h>
using namespace std;
//int main()
//{
//	printf("hello world");
//	return 0;
//}int main()
{cout << "hello world" << "  " << "123" << endl;return 0;
}

在这里插入图片描述
从结果中就可以验证我们上面所说的话;
而且在这里如果熟悉C语言的我们可以看出来流插入运算符,与我们C语言中的按位左移运算符相同,由于C++兼容C语言,区分就成了问题,所以就有了我们下面要讲的运算符重载

通过重载,同一个运算符将有不同的含义。编译器通过上下文来确定运算符的含义。C本身也有一些运算符重载的情况。例如,&符号既表示地址运算符,又表示按位AND运算符;*既表示乘法,又表示对指针解除引用。这里重要的不是这些运算符的具体功能,而是同一个符号可以有多种含义,而编译器可以根据上下文来确定其含义。C++扩展了运算符重载的概念,允许为用户定义的类型(类)重新定义运算符的含义。

输入

2.输入:cin >> a;

#include <iostream>int main() {int num;std::cout << "Enter an integer: ";std::cin >> num;std::cout << "The number you entered is " << num << std::endl;return 0;
}

这个示例中,我们使用 std::cin 来从键盘读取一个整数,并将该整数存储在变量 num 中。我们还使用 std::cout 向用户输出提示信息和最终的整数值。
cin 可以读取各种类型的输入值,包括整数、浮点数、字符和字符串。

cin和scanf的对比

cin 支持所有 C++ 内置类型的数据输入,包括 int, float, double 等。 它还支持用户定义的数据类型,例如类和结构。另一方面,scanf 函数只支持 C 语言的基本类型,如 int, char, float, double 等。它不支持 C++ 类和结构体。
错误处理:
cin 使用构造函数抛出异常来处理输入错误。当您尝试读取不合适的类型或不是具有所需范围的类型的值时,会抛出一个异常。这使得可以在程序的其他部分捕获该异常,并对用户做出适当的反应。另一方面,scanf 使用返回值来指示输入的成功与否,并且没有异常。
性能:

1.cin 的性能可能比 scanf 高,因为前者通常使用循环和条件语句来处理输入,而后者通过从输入流中查找特定的字符进行输入。因此,使用 cin 可以更高效地读取大量的输入数据。
可读性和便携性:
2.cin 的语法和功能比 scanf 更易于理解和编写。 cin 使用各种工具,例如流插入和流提取符,使读取和写入数据的操作更直观。此外,cin 在 C++ 标准中定义,因此可在所有的 C++ 编译器中使用。

2.命名空间

2.1namespace存在的意义

在C/C++中,变量、函数和后⾯要学到的类都是⼤量存在的,这些变量、函数和类的名称将都存在于全局作⽤域中,可能会导致很多冲突。
使⽤命名空间的⽬的是对标识符的名称进⾏本地化,以避免命名冲突或名字污染,
namespace关键字的出现就是针对这种问题的。

namespace(命名空间)是一种用于组织代码中命名的机制。它提供了一种方法来避免命名冲突,并允许您创建多个具有相同名称的独立实体。
定义命名空间
可以使用以下语法来定义命名空间并指定其名称:

//text.cpp
namespace my_namespace {// 在这里定义命名空间的成员
}

我们通过一个C语言中错误的代码来理解:

#include <stdlib.h>
int rand = 10;
int main()
{// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数”printf("%d\n", rand);return 0;
}

而在C++中我们可以通过在命名空间中定义它来更好的解决;

2.2namespace的使用

• 定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中
即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
• namespace本质是定义出⼀个域,这个域跟全局域各⾃独⽴,不同的域可以定义同名变量,所以下
⾯的rand不在冲突了。
• C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/
类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响
编译查找逻辑,还会影响变量的⽣命周期,命名空间域和类域不影响变量⽣命周期。

  1. namespace只能定义在全局,当然他还可以嵌套定义。

2.项⽬⼯程中多⽂件中定义的同名namespace会认为是⼀个namespace,不会冲突。
3.C++标准库都放在⼀个叫std(standard)的命名空间中。

在使用命名空间的成员时,我们需要使用名称空间的名称将其导入到当前范围。

#include<iostream>
using namespace std;
namespace study
{//变量int arr = 1;//函数int ADD(int left, int right){return left + right;}//结构体struct Node{struct Node* next;int val;};
}int main()
{cout << study::ADD(1, 2) << endl;return 0;
}

编译查找⼀个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间⾥⾯去查找。所以
下⾯程序会编译报错。所以我们要使⽤命名空间中定义的变量/函数,有三种⽅式:

• 1.指定命名空间访问,项⽬中推荐这种⽅式。
• 2.using将命名空间中某个成员展开,项⽬中经常访问的不存在冲突的成员推荐这种⽅式。
• 3.展开命名空间中全部成员,项⽬不推荐,冲突⻛险很⼤,⽇常⼩练习程序为了⽅便推荐使⽤。

// 指定命名空间访问
int main()
{printf("%d\n", N::a);return 0;
}// using将命名空间中某个成员展开
using N::b;
int main()
{printf("%d\n", N::a);printf("%d\n", b);return 0;
}
//展开整个命名空间中的全部成员;
#include <iostream>namespace my_namespace {void some_function() {std::cout << "Hello from my_namespace!" << std::endl;}
}
using namespace my_namespace;
int main() {some_function();return 0;
}

这里还有一个问题,当我们有两个命名空间,它们都定义了一个名为 sayHello 的函数。

// 在命名空间 `test` 中定义 `sayHello` 函数
namespace test {void sayHello() {std::cout << "Hello from test!" << std::endl;}
}// 在命名空间 `test2` 中定义 `sayHello` 函数
namespace test2 {void sayHello() {std::cout << "Hello from test2!" << std::endl;}
}int main() {using namespace test;using namespace test2;sayHello();return 0;
}

在这个示例中,我们使用 using 语句导入了 test 命名空间中的 sayHello 函数和 test2 命名空间中的 sayHello 函数。当我们调用 sayHello 函数时,C++ 编译器并不知道是调用 test::sayHello 还是 test2::sayHello。 在运行期间与两个函数冲突。
为了避免这种情况,您可以在每个命名空间中导入只自己需要的成员,或者在使用命名空间成员时显式引用命名空间,以确保编译器知道调用哪个函数。例如,
在这里插入图片描述
这时的解决方法就是显式引用了每个命名空间中的 sayHello 函数,以确保编译器知道我们正在调用哪个函数:

#include <iostream>namespace test {void sayHello() {std::cout << "Hello from test!" << std::endl;}
}namespace test2 {void sayHello() {std::cout << "Hello from test2!" << std::endl;}
}int main() {test::sayHello();test2::sayHello();return 0;
}

3.缺省参数

• 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时,如果没有指定实参
则采⽤该形参的缺省值,否则使⽤指定的实参,缺省参数分为全缺省和半缺省参数。(有些地⽅把
缺省参数也叫默认参数)
• 全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左
依次连续缺省,不能间隔跳跃给缺省值。
• 带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。
• 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。

#include <iostream>
#include <assert.h>
using namespace std;
void Func(int a = 0)
{cout << a << endl;
}
int main()
{Func(); // 没有传参时,使⽤参数的默认值Func(10); // 传参时,使⽤指定的实参return 0;
}
#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);return 0;
}

在这里插入图片描述

4.函数重载

C++支持在同一作用域中定义多个同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样C++函数调⽤就表现出了多态⾏为,使⽤更灵活。C语⾔是不⽀持同⼀作⽤域中出现同名函数的。

#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{cout << "int Add(int left, int right)" << endl;return left + right;
}
double Add(double left, double right)
{cout << "double Add(double left, double right)" << endl;return left + right;
}
// 2、参数个数不同
void f()
{cout << "f()" << endl;
}
void f(int a)
{cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
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;
}
// 返回值不同不能作为重载条件,因为调⽤时也⽆法区分
//void fxx()
//{}
//
//int fxx()
//{
// return 0;
//}
// 下⾯两个函数构成重载
// f()但是调⽤时,会报错,存在歧义,编译器不知道调⽤谁
void f1()
{cout << "f()" << endl;
}
void f1(int a = 10)
{cout << "f(int a)" << endl;
}
int main()
{Add(10, 20);Add(10.1, 20.2);f();f(10);f(10, 'a');f('a', 10);return 0;
}

在这里插入图片描述

重载函数的调用规则

1.参数数量(或参数的顺序)应与函数定义匹配。
2.参数类型应与函数定义中参数类型匹配(考虑到 C++ 的类型转换基本原则)。如果函数定义中提供有默认的参数值,则重载函数调用时可以省略该描述符所引用的参数。

#include <iostream>// 无参数的原型
void sideFunction() {std::cout << "Call with no parameters" << std::endl;
}// 双参数原型,整型和双精度型参数
void sideFunction(int num, double num2) {std::cout << "Call with int and double arguments: " << num << " " << num2 << std::endl;
}int main() {sideFunction();           // 调用无参数版本的 sideFunction()sideFunction(10, 3.14);   // 调用 int 和 double 参数版本的 sideFunction()return 0;
}

5.引用

引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间,
它和它引⽤的变量共⽤同⼀块内存空间。
形式表现为:类型& 引用别名 = 引用对象;
并且它可以有多个引用别名;

int& a = b;
int& c = a;
此时a是b的引用别名;(**不要把引用符号“&”和取地址符号混淆**)
对别名a取别名c,c相当于还是a的别名;

它是与变量相关联的指针,但与其他指针不同,引用必须初始化指向某个已存在的对象,并且在整个其生命周期中都必须指向那个对象。引用就像指针一样,但是它们的一些优点是:

1.引用不像指针那样需要显式解引用操作。引用允许直接访问其引用的值,而不需要使用""运算符。
2.由于引用必须在初始化时被绑定到某个对象,因此不会出现悬空引用问题。
3.由于引用初始化不能更改,因此避免了错误的引用传递问题,即在函数调用传递引用时未提供有效的引用

引用必须在定义的同时初始化,并且在之后的程序里不能改变引用的指向;
对于这句话的理解,我们看下面一段代码;

#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;return 0;
}

这里面的b = c并非改变了引用指向,而是赋值,因为如果是改变了引用指向,根据我们上面给出的定理,引用别名和变量共用一块地址,所以我们只需要看它们的地址是否相同就能够判断出;
在这里插入图片描述
从地址中我们可以看出b 和 c 的地址并不相同,所以b = c只是赋值;

而下面这段代码中的形式,才是改变了引用指向;

#include <iostream>
using namespace std;int main() {int a = 99, b = 32;int &r = a;a = 67;cout << a << ", " << r << endl; //67,67&r=b;//不能重新引用其他数据b = 88;cout << b << ", " << r << endl;return 0;
}

结果会报错为表达式必须为可修改的左值;在这里插入图片描述
最后对于引用中另外的关键知识点和问题,后面我会再写一篇文章专门讲解
在这里插入图片描述

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

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

相关文章

钡铼网关实时数据互联,加速IEC104与MQTT云平台对接

随着工业4.0时代的到来&#xff0c;电力系统中的数据采集、监控与远程控制需求日益增长。IEC 104&#xff08;IEC 60870-5-104&#xff09;作为国际电工委员会&#xff08;IEC&#xff09;制定的电力自动化通信协议&#xff0c;广泛应用于电力系统的状态监测、数据采集和设备控…

【推研小灶】复旦与南大之间:一次独特的计算机保研之旅

写在前面 上午10点填完志愿等待复试通知&#xff0c;利用这段时间记录一下我简短的夏令营和预推免。今年变为线下之后&#xff0c;部分学校的入营情况、考核方式有明显变化。加上CS方向保研名额总体变多&#xff0c;形势有点小乱&#xff0c;甚至填报系统都在9.29中秋节当天&a…

如何优化 Nginx 处理特定 MIME 类型的性能?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; 文章目录 如何优化 Nginx 处理特定 MIME 类型的性能&#xff1f;一、了解 MIME 类型二、分析性能瓶颈三、优化配置1. 开启 Gzip 压缩2. 调整缓存策略3. 优化服务器资源分配…

【C++进阶学习】第九弹——哈希的原理与实现——开放寻址法的讲解

前言&#xff1a; 在前面&#xff0c;我们已经学习了很多存储机构&#xff0c;包括线性存储、树性存储等&#xff0c;并学习了多种拓展结构&#xff0c;效率也越来越高&#xff0c;但是是否有一种存储结构可以在大部分问题中都一次找到目标值呢&#xff1f;哈希可能能实现 目录…

el-tree树添加向下移动按钮,前端界面调整顺序

需求&#xff1a;树上添加向下按钮&#xff0c;再不调用接口的情况下&#xff0c;调整树的顺序结构 遇到的问题&#xff1a;第一次点击更新的&#xff0c;数据和视图是调整好的&#xff0c;再次点击页面调整顺序&#xff0c;只有数据被调整了&#xff0c;视图没有发生改变。 &…

我澄清下,大数据界面虽然有点花,但对趋势的判断还是很准的!

我澄清下&#xff0c;大数据界面虽然有点花&#xff0c;但对趋势的判断还是很准的&#xff01; 艾斯视觉的观点认为&#xff1a;在这个充满不确定性的世界里&#xff0c;大数据就像一位智者&#xff0c;透过那些令人眼花缭乱的界面&#xff0c;总能以它独到的洞察力&#xff0…

链路聚合加单臂路由

一、实验目的及拓扑 实验目的&#xff1a;在路由器及交换机之间建立链接聚合&#xff0c;交换机接入两台主机并通过路由器子接口自动分配IP地址&#xff0c;通过单臂路由实现两台主机互联 二、基本配置 1、交换机配置 [S1]vlan batch 10 20 [S1-Eth-Trunk1]dis th # interf…

eclipse ui bug

eclipse ui bug界面缺陷&#xff0c;可能项目过多&#xff0c;特别maven项目过多&#xff0c;下载&#xff0c;自动编译&#xff0c;加载更新界面异常 所有窗口死活Restore不回去了 1&#xff09;尝试创建项目&#xff0c;还原界面&#xff0c;失败 2&#xff09;关闭所有窗口&…

mysql面试(六)

前言 本章节详细讲解了一下mysql执行计划相关的属性释义&#xff0c;以及不同sql所出现的不同效果 执行计划 一条查询语句经过mysql查询优化器的各种基于成本和各种规则优化之后&#xff0c;会生成一个所谓的 执行计划&#xff0c;这个执行计划展示了这条查询语句具体查询方…

模拟can信号实现通信

实车上算法一般通过ros进行通信&#xff0c;车辆和控制器之间则通过can通信实现&#xff0c;今天来学习一下如何模拟这个can。 can信号的发送和接收一般是需要载体的&#xff0c;我们一般都有can0和can1设备可以使用&#xff0c;在电脑上创建这个设备&#xff1a; 加载vcan内核…

数据库开发:MySQL基础(二)

MySQL基础&#xff08;二&#xff09; 一、表的关联关系 在关系型数据库中&#xff0c;表之间可以通过关联关系进行连接和查询。关联关系是指两个或多个表之间的关系&#xff0c;通过共享相同的列或键来建立连接。常见的关联关系有三种类型&#xff1a;一对多关系&#xff0c;…

Talk|新加坡国立大学赵轩磊:Pyramid Attention Broadcast - 通向视频模型的实时生成

本期为TechBeat人工智能社区第612期线上Talk&#xff01; 北京时间7月25日(周四)20:00&#xff0c;新加坡国立大学博士生—赵轩磊的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “Pyramid Attention Broadcast - 通向视频模型的实时生成”&#x…

Spring Boot中如何实现全链路调用日志跟踪?

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 引言 在Spring Boot中实现全链路调用日志跟踪&#xff0c;主要依赖于Mapped Diagnostic Context&#xff08;MDC&#xff09;功能。MDC是一种用于在多线程条件下记录日志的功能&#xff0c;它可以看作是与当…

深入分析 Android ContentProvider (五)

文章目录 深入分析 Android ContentProvider (五)ContentProvider 的性能优化和实践案例1. 性能优化技巧1.1. 数据库索引优化示例&#xff1a;添加索引 1.2. 批量操作与事务管理示例&#xff1a;批量插入操作 1.3. 使用异步操作示例&#xff1a;使用 AsyncTask 进行异步查询 1.…

Nodejs实现微信订阅消息的发送

关于Nodejs的项目配置和路由配置我这里就不过多叙述了。着重关于订阅消息的发送 1.首先前往微信开发者平台配置好自己的订阅消息模板&#xff08;改版后的只支持一次性订阅&#xff1a;每次用户操作记录一次&#xff0c;openid只能发送一次消息给用户&#xff0c;不能持续订阅…

每日一知识点- Java 方法重载和方法重写

目录 &#x1f4dd; 每日一知识点方法重载方法重写 &#x1f4ce; 参考文章 &#x1f600; 准备好了吗&#xff1f;让我们一起步入这座Java神奇的城堡&#xff0c;揭开方法重载&#xff08;Overloading&#xff09;和方法重写&#xff08;Overriding&#xff09;的神秘面纱。 &…

基于迁移学习的手势分类模型训练

1、基本原理介绍 这里介绍的单指模型迁移。一般我们训练模型时&#xff0c;往往会自定义一个模型类&#xff0c;这个类中定义了神经网络的结构&#xff0c;训练时将数据集输入&#xff0c;从0开始训练&#xff1b;而迁移学习中&#xff08;单指模型迁移策略&#xff09;&#x…

一文掌握YOLOv1-v10

引言 YOLO目标检测算法&#xff0c;不过多介绍&#xff0c;是基于深度学习的目标检测算法中最出名、发展最好的检测器&#xff0c;没有之一。本文简要的介绍一下从YOLOv1-YOLOv10的演化过程&#xff0c;详细技术细节不过多介绍&#xff0c;只提及改进点&#xff0c;适合初学者…

Vue3二次封装axios

官网: https://www.axios-http.cn/docs/interceptors steps1: 安装 npm install axios -ssteps2: /src/api/request.js 文件 >>> 拦截器 import axios from axios // 如果没用element-plus就不引入 import { ElMessage } from element-plusconst service axios.cre…

7月22日学习笔记 文件共享服务nfs,SAMBA文件共享与DNS域名服务

任务背景 由于业务驱动&#xff0c;为了提⾼⽤户的访问效率&#xff0c;现需要将原有web服务器上的静态资源 ⽂件分离出来&#xff0c;单独保存到⼀台⽂件服务器上。 任务要求 1. ⼀台应⽤服务器web-server部署apache&#xff0c;静态⽹⻚资源存放在另外⼀台NFS服 务器上 …