初识C++【命名空间】【输入输出】【缺省参数】【函数重载】

news2024/9/22 11:27:18

前言

C++是一种通用的编程语言,被广泛用于开发各种应用程序,包括系统软件、游戏、手机应用和高性能计算等。它是C语言的扩展,添加了许多新特性和功能,并支持面向对象编程。C++可以在不同的平台上编译和运行,具有高效性、可移植性和灵活性等特点。它的语法和语义与C语言相似,但还包括了类、模板、异常处理和STL(标准模板库)等特性。C++是一种强大而灵活的编程语言。简单的说,C++就是C语言的plus版本,C++的出现就是建立在C语言之上的。

一.命名空间

命名空间(Namespace)是一种组织和管理代码的方式,它将代码分组并提供了唯一的标识符(名称)来引用这些代码。它的主要作用是避免命名冲突,让不同模块或代码库中的同名元素能够被准确地引用。举个例子:

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

如果我把这个代码放到编译器里编译就会出现报错,说的是我们的rand重定义了。那是因为在头文件stdlib里我们有rand这个函数。这就是命名冲突了。

1.1namespace的价值

在C/C++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的就是对标识符的名称进行本地化,以避免命名冲突或名字污染,这时在我们的C++里面就引入了一个叫namespace的东西,在东西就可以很好的解决掉命名冲突的问题。

1.2namespace的定义

1.定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员(值得注意的是在{}后面不加;)。命名空间中可以定义变量/函数/类型等。
就像是这样:
#include<stdio.h>
#include <stdlib.h>
namespace lwz
{
	//在命名空间里可以是变量、函数和类型
	int rand = 10;

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

	struct LNode
	{
		int* a;
		struct LNode* next;
	};
}
int main()
{
	
	// 这里默认是访问的是全局的rand函数指针
	printf("%p\n", rand);
	// 这里指定lwz命名空间中的rand
	printf("%d\n",lwz::rand);
	return 0;
}
2.namespace本质是定义出一个域,这个域跟全局域各自独立,不同的域可以定义同名变量,所以下面的rand不在冲突了。
3.C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。
4.namespace只能定义在全局,当然他还可以嵌套定义。
像是这样:
namespace a
{
	namespace b
	{
		int Add(int x, int y)
		{
			return x + y;
		}
	}
	namespace c
	{
		int Add(int x, int y)
		{
			return x + y;
		}
	}
}
int main()
{
	printf("%d\n", a::b::Add(1, 2));
	printf("%d\n", a::c::Add(2, 2));
	return 0;
}

这里我在命名空间a里嵌套了两个命名空间b和c,在我们使用的时候,用::就可以访问命名空间里的东西了。

5.项目工程中多文件中定义的同名namespace会认为是⼀个namespace,不会冲突。
这句话的意思就是,假如我创建了多个.cpp的文档,并且我都创建了一个名字为lwz的命名空间,那么在运行的时候,会认为这些文档里lwz都是一个东西,可以理解为把所有名字为lwz的命名空间都合在一起了。
6.C++标准库都放在⼀个叫std(standard)的命名空间中。

1.3命名空间的使用

编译查找⼀个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以
下⾯程序会编译报错。所以我们要使用命名空间中定义的变量/函数,有三种方式:
指定命名空间访问,项目中推荐这种方式。
这种方式就是上面我一直用到的方式:
namespace lwz
{
	int a = 0;
	int b = 10;
}
int main()
{
	printf("%d\n", lwz::a);
	printf("%d\n", lwz::b);
	return 0;
}
using将命名空间中某个 成员展开,项目中经常访问的不存在冲突的成员推荐这种方式。
展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
展开的方式也可以使用,但是风险很大:
namespace lwz
{
	int a = 0;
	int b = 10;
}
using namespace lwz;
int main()
{
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

using的作用就是展开我们的命名空间,可以理解为把lwz域里的东西拿到全局域里。当然也可以单独的把命名空间里的某个特殊成员展开。

namespace lwz
{
	int a = 0;
	int b = 10;
}
using lwz::a;
int main()
{
	printf("%d\n", a);
	printf("%d\n", lwz::b);
	return 0;
}

二.输入输出

虽然C++是兼容C语言的,但是C++还是有自己的一套输入输出。我先简单的写一个输入输出:

#include<iostream>
using namespace std;
int main()
{
	int a = 0;
	double b=0.0;
	char c = 'a';
	std::cout << a << " " << b << " " << c <<std::endl;
	//我们在输出时可以自动的识别变量的类型

	cin >> a >> b >> c;
	//输入1 2.222 x
	cout << a << " " << b << " " << c << endl;
	//输出1 2.222 x
	return 0;
}
<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系列 编译器是这样的,其他编译器可能会报错。

三.缺省参数

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)

#include<iostream>
using namespace std;
void Func(int a = 0)
{
	cout << a << 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);
	return 0;
}

值得注意的是,在半缺省里,函数不可以是void Func2(int a=10, int b, int c = 20)或者void Func2(int a=10, int b, int)。

带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参。

这里也就刚好对应上面的那一条,半缺省参数必须是从右往左依次连续缺省。

函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省
值。
这里我来解释一下这句话,当时我在用C语言实现栈的时候,我把函数的声明和定义放到了两个文档里面。此时的声明和定义是分离的,在实现栈的初始化的时候,我们可以用一个缺省参数来实现:
首先这是Stack.h文件:
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;
void STInit(ST* ps, int n = 4);

此时我们已经在Stack.h文件里已经有了缺省参数,然后是.cpp文件:

#include"Stack.h"
void STInit(ST* ps, int n=10)
{
	assert(ps && n > 0);
	ps->a = (STDataType*)malloc(n * sizeof(STDataType));
	ps->top = 0;
	ps->capacity = n;
}

如果继续再函数定义这里还有缺省参数的话,就会导致重定义的问题出现。所以一定要是在函数声明给缺省值。

四.函数重载

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

4.1参数类型不同

#include <iostream>
#include <assert.h>
using namespace std;
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;
}
int main()
{
	Add(1, 2);
	Add(1.23, 2.13);
	return 0;
}

最终打印出“”

4.2参数个数不同

void f()
{
	cout << "f()" << endl;
}
void f(int a)
{
	cout << "f(int a)" << endl;
}
int main()
{
	f();
	f(10);
	return 0;
}

最后打印出:

 

4.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;
}

最终打印出:

 

4.4其他情况 

值得注意的是,返回值不同不能作为重载条件,因为调用的时候也无法区分。

包括还有一种情况也会报错:

void f1()
{
cout << "f()" << endl;
}
void f1(int a = 10)
{
cout << "f(int a)" << endl;
}

假如我调用的时候没有参数,编译器就不知道调用谁。

到这里我简单的介绍了几个简单的C++的语法,也是C++入门必须要知道的东西,如有错误还请多多指出,感谢观看。 

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

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

相关文章

C++:C++入门基础|命名空间|输入输出

欢迎来到HarperLee的学习笔记&#xff01; 博主主页传送门&#xff1a; HarperLee的博客主页! 想要一起进步的uu来后台哦&#xff01; 一、什么是C? 在此之前&#xff0c;我们所学习的C语言是一种结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&a…

【Java算法】二分查找 下

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【算法工作坊】算法实战揭秘 一.山脉数组的峰顶索引 题目链接&#xff1a;852.山脉数组的峰顶 ​ 算法原理 这段代码实现了一个查找山峰数组中峰值索引的算法。山峰数组是一个先递增后递减的数组&…

14-55 剑和诗人29 - RoSA:一种新的 PEFT 方法

介绍 参数高效微调 (PEFT) 方法已成为 NLP 领域研究的热门领域。随着语言模型不断扩展到前所未有的规模&#xff0c;在下游任务中微调所有参数的成本变得非常高昂。PEFT 方法通过将微调限制在一小部分参数上来提供解决方案&#xff0c;从而以极低的计算成本在自然语言理解任务上…

QT入门看这一篇就够(详解含qt源码)

目录 一、Qt概述 1.1 什么是Qt 1.2 Qt的发展史 1.3 Qt的优势 1.4 Qt版本 1.5 成功案例 二、创建Qt项目 2.1 使用向导创建 2.2 一个最简单的Qt应用程序 2.2.1 main函数中 2.2.2 类头文件 2.3 .pro文件 2.4 命名规范 2.5 QtCreator常用快捷键 三、Qt按钮小程序 …

【技术选型】MySQL、Oracle、Postgresql如何选择

【技术选型】MySQL、Oracle、Postgresql如何选择 开篇词&#xff1a;干货篇&#xff1a;MySQL&#xff1a;Oracle&#xff1a;PostgreSQL&#xff1a; 总结篇&#xff1a;我是杰叔叔&#xff0c;一名沪漂的码农&#xff0c;下期再会&#xff01; 开篇词&#xff1a; 常见几种关…

Nuxt框架中内置组件详解及使用指南(四)

title: Nuxt框架中内置组件详解及使用指南&#xff08;四&#xff09; date: 2024/7/9 updated: 2024/7/9 author: cmdragon excerpt: 摘要&#xff1a;本文详细介绍了Nuxt 3框架中的两个内置组件&#xff1a;和的使用方法与示例。用于捕获并处理客户端错误&#xff0c;提供…

图解HTTP(5、与 HTTP 协作的 Web 服务器 6、HTTP 首部)

5、与 HTTP 协作的 Web 服务器 一台 Web 服务器可搭建多个独立域名的 Web 网站&#xff0c;也可作为通信路径上的中转服务器提升传输效率。 用单台虚拟主机实现多个域名 在相同的 IP 地址下&#xff0c;由于虚拟主机可以寄存多个不同主机名和域名的 Web 网站&#xff0c;因此…

回溯算法-以学生就业管理系统为例

1.回溯算法介绍 1.来源 回溯算法也叫试探法&#xff0c;它是一种系统地搜索问题的解的方法。 用回溯算法解决问题的一般步骤&#xff1a; 1、 针对所给问题&#xff0c;定义问题的解空间&#xff0c;它至少包含问题的一个&#xff08;最优&#xff09;解。 2 、确定易于搜…

[ios-h5]在ios系统浏览器中输入框得到焦点时页面自动放大

问题&#xff1a; 在ios系统浏览器中输入框得到焦点时页面自动放大。 解决&#xff1a; 添加meta标签。 <meta name"apple-mobile-web-app-capable" content"yes" /> <meta name"viewport" content"widthdevice-width, initial-…

循环练习题

思路&#xff1a; 代码&#xff1a; public static void main(String[] args) {double sum0;for (int i1;i<100;i){if (i%2!0){sum1.0/i;}else {sum-1.0/i;}}System.out.println(sum);} 结果为&#xff1a;

每日一练 - RSTP响应端口故障后的处理流程

01 真题题目 在如图所示的网络中&#xff0c; 所有的交换机运行 RSTP 协议&#xff0c; 假如 SWB 的 E 1 接口故障后&#xff0c; RSTP 的处理过程是&#xff1a;(多选) A.SWB 删除 MAC 地址表中以 E 1 为目的端口的端口表项。 B.重新计算生成树&#xff0c;选举 E2 为新的根…

ER模型理论和三范式

ER模型理论和三范式 各种关系多对一一对一一对多多对多 三范式理论函数依赖完全函数依赖部分函数依赖传递&#xff08;间接&#xff09;函数依赖 第一范式&#xff1a;属性&#xff08;表字段&#xff09;不可切割第二范式&#xff1a;不能存在 部分函数依赖(都存在完全函数依赖…

为什么3d模型在透视里面闪烁?---模大狮模型网

在展览3D模型设计中&#xff0c;透视效果是展示空间深度和立体感的重要手段。然而&#xff0c;有时候我们会面对3D模型在特定透视角度下出现闪烁或者失真的问题。本文将深入探讨这一现象的原因及解决方法&#xff0c;帮助设计师们更好地理解和处理这类挑战。 一、为什么3D模型在…

Maven在Windows中的配置方法

本文介绍在Windows电脑中&#xff0c;下载、配置Maven工具的详细方法。 Maven是一个广泛使用的项目管理工具&#xff0c;主要针对Java项目&#xff0c;但也可以用于其他类型的项目&#xff1b;其由Apache软件基金会维护&#xff0c;旨在简化和标准化项目构建过程&#xff0c;依…

Tomcat的安全配置

1、生产环境优化 2、部分漏洞修复 转载自风险评估&#xff1a;Tomcat的安全配置&#xff0c;Tomcat安全基线检查加固-CSDN博客

SpringBoot实战:轻松实现接口数据脱敏

文章目录 引言一、接口数据脱敏概述1.1 接口数据脱敏的定义1.2 接口数据脱敏的重要性1.3 接口数据脱敏的实现方式 二、开发环境三、实现接口返回数据脱敏3.1 添加依赖3.2 创建自定义注解3.3 定义脱敏枚举类3.4 创建自定义序列化类 四、测试4.1 编写测试代码4.2 测试 五、总结 引…

如何在 SwiftUI 中开发定制 MapKit 功能

文章目录 介绍地图样式imagery-map 地图交互地图控件总结 介绍 在上一篇文章中&#xff0c;我们探讨了 SwiftUI 中新的 MapKit API 的基础知识。现在&#xff0c;让我们深入 MapKit API 的定制点&#xff0c;以便根据我们的需求定制地图呈现。 地图样式 新的 MapKit API 引入…

晶体振荡器:频率的广度与应用的深度

晶体振荡器&#xff0c;以其无与伦比的频率稳定性和广泛的应用范围&#xff0c;成为现代电子工程的基石。从低至0.0320MHz的细腻频率到高达1075MHz以上的雄壮音符&#xff0c;晶体振荡器跨越了广阔频谱&#xff0c;为计时、通信、高级电子系统乃至宇宙探索提供了精准的时间基准…

PyCharm在线版,一周使用总结!!!

前言 过去一周&#xff0c;对pycharm在线版进行了使用&#xff0c;对云原生开发工具有了全新的认识&#xff0c;云原生开发是一种现代化的软件开发和部署方法&#xff0c;它充分利用了云计算的优势&#xff0c;特别是容器化、微服务、持续集成/持续部署&#xff08;CI/CD&…

【界面态】霍尔效应表征氮化对SiC/SiO2界面陷阱的影响

引言 引言主要介绍了硅碳化物&#xff08;SiC&#xff09;金属-氧化物-半导体场效应晶体管&#xff08;MOSFETs&#xff09;作为新一代高压、低损耗功率器件的商业化背景。SiC MOSFETs因其优越的电气特性&#xff0c;在高电压和高温应用领域具有巨大的潜力。然而&#xff0c;尽…