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

【C++初阶】C++入门(一)

大家好我是沐曦希💕

文章目录

  • 1.前言
  • 2.C++关键字(C++98)
  • 3.命名空间namespace
    • 3.1 命名空间定义
    • 3.2 命名空间使用
      • 3.2.1 加命名空间名称及作用域限定符
      • 3.2.2 使用using将命名空间中某个成员引入
      • 3.2.3 使用using namespace 命名空间名称 引入
  • 4.C++输入&输出
    • 4.1 命名空间完全展开
    • 4.2 命名空间的指定
    • 4.3 命名空间的部分展开
  • 5.缺省参数
    • 5.1 缺省参数概念
    • 5.2 缺省参数分类
      • 5.2.1 全缺省参数
      • 5.2.2 半缺省参数
    • 缺省参数应用场景
  • 6.写在最后

1.前言

C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。熟悉C语言之后,对C++学习有一定的帮助,C++入门主要目标:

  1. 补充C语言语法的不足,以及C++是如何对C语言设计不合理的地方进行优化的,比如:作用域方面、IO方面、函数方面、指针方面、宏方面等。
  2. 为后续类和对象学习打基础

2.C++关键字(C++98)

C++总计63个关键字,C语言32个关键字

asmdoifreturntrycontinue
autodoubleinlineshorttypedeffor
booldynamic_castintsignedtypeidpublic
breakelselongsizeoftypenamethrow
caseenummutablestaticunionwchar_t
catchexplicitnamespacestatic_castunsigneddefault
charexportnewstructusingfriend
classexternoperatorswitchvirtualregister
constfalseprivatetemplatevoidtrue
const_castfloatprotectedthisvolatilewhile
deletegotoreinterpret_cast

3.命名空间namespace

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

#include<stdio.h>
#include<stdlib.h>
int rand = 10;
// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{
	printf("%d\n", rand);
	return 0;
}

编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”

#include<stdio.h>
namespace test
{
	int rand = 10;
}
int main()
{
	printf("%d\n", rand);//函数的地址
	return 0;
}

在这里插入图片描述
而C++标准库的函数等放进std的命名空间里去。

3.1 命名空间定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员

#include<stdio.h>
// lj是命名空间的名字,一般开发中是用项目名字做命名空间名。
// 命名空间的名字可以按照直接喜好来拟定
// 1. 正常的命名空间定义.
namespace lj
{
	// 命名空间中可以定义变量/函数/类型
	int rand = 10;
	int Add(int left, int right)
	{
		return left + right;
	}
	struct Node
	{
		struct Node* next;
		int val;
	};
}
//2.命名空间可以嵌套
//test.cpp
namespace N1
{
	int rand = 10;
	int Sub(int left, int right)
	{
		return left - right;
	}
	namespace N2
	{
		int rand = 20;
		void Swap(int* left, int* right)
		{
			int tmp = *left;
			*left = *right;
			*right = tmp;
		}
	}
}
//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
// ps:一个工程中的test.h和上面test.cpp中两个N1会被合并成一个
//test.h
namespace N1
{
	int a = 10;
	int b = 20;
	int Mul(int left, int right)
	{
		return left * right;
	}
}

注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。

需要注意的是:只有同一级的相同名称的命名空间在编译运行时候,才会被合并。不同命名空间/域中可以定义同一个变量。同一个命名空间不能定义同一个变量。
放在命名空间的变量,不会影响该变量的生命周期,只是限定域,影响了编译器的查找规则(先找局部,后找全局),编译器在编译和运行时候不会查找在命名空间的定义的变量和函数,相当于增加了一堵墙。

namespace N1
{
	int rand = 10;//全局变量(放在静态区)
}
namespace N2
{
	int rand = 20;//全局变量
}

3.2 命名空间使用

那么命名空间如何使用呢?

namespace bit
{
	// 命名空间中可以定义变量/函数/类型
	int a = 0;
	int b = 1;
	int Add(int left, int right)
	{
		return left + right;
	}
	struct Node
	{
		struct Node* next;
		int val;
	};
}
int main()
{
	// 编译报错:error C2065: “a”: 未声明的标识符
	printf("%d\n", a);
	return 0;
}

命名空间的使用有三种方式

3.2.1 加命名空间名称及作用域限定符

int main()
{
	printf("%d\n", N::a);
	return 0;
}

在这里插入图片描述

3.2.2 使用using将命名空间中某个成员引入

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

在这里插入图片描述

3.2.3 使用using namespace 命名空间名称 引入

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

在这里插入图片描述

4.C++输入&输出

4.1 命名空间完全展开

#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
//将std命名空间的内容展开,用起来就方便,相当于把命名空间的隔离墙拆了
int main()
{
	cout << "Hello world!!!" << endl;
	return 0;
}

说明:

  1. 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。
  2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含头文件中。
  3. <<是流插入运算符,>>是流提取运算符。
  4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。C++的输入输出可以自动识别变量类型
  5. 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,这些知识后续会学习,这里只是简单讲解他们的使用。

C++自动识别变量的类型本质是:函数重载

注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用+std的方式

4.2 命名空间的指定

#include<iostream>
int main()
{
	std::cout << "hello world" << std::endl;
	return 0;
}

::域作用的限定符

取到全局变量的值:

#include<stdio.h>
int a = 10;
int main()
{
	int a = 100;
	printf("%d\n", a);
	printf("%d\n", ::a);
	return 0;
}

在这里插入图片描述

4.3 命名空间的部分展开

#include<iostream>
using std::cout;
using std::endl;
int main()
{
	cout << "hello world" << endl;
	return 0;
}
#include <iostream>
using namespace std;
int main()
{
	int a;
	double b;
	char c;
	// 可以自动识别变量的类型
	cin >> a;
	cin >> b >> c;
	cout << a << endl;
	cout << b << " " << c << endl;
	return 0;
}
// ps:关于cout和cin还有很多更复杂的用法,比如控制浮点数输出精度,控制整形输出进制格式等等。因为C++兼容C语言的用法,这些又用得不是很多.

在这里插入图片描述

std命名空间的使用惯例:
std是C++标准库的命名空间,如何展开std使用更合理呢?

  1. 在日常练习中,建议直接using namespace std即可,这样就很方便。
  2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 +using std::cout展开常用的库对象/类型等方式。

5.缺省参数

5.1 缺省参数概念

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

#include<iostream>
using namespace std;
void Func(int a = 0)
{
	cout << a << endl;
}
int main()
{
	Func(); // 没有传参时,使用参数的默认值
	Func(10); // 传参时,使用指定的实参
	return 0;
}

在这里插入图片描述
缺省需要注意的是:只能从右往左连续缺省。缺省必须是局部变量和全局变量,缺省参数不能在函数声明和定义中同时出现,只能在声明中即.h头文件中定义缺省参数。

5.2 缺省参数分类

5.2.1 全缺省参数

#include<iostream>
using namespace std;
void Func(int a = 10, int b = 20, int c = 30)
{
	cout << "a =" << a << endl;
	cout << "b =" << b << endl;
	cout << "c =" << c << endl;
	cout << endl;
}
int main()
{
	Func();
	Func(1);
	Func(1, 2);
	Func(1, 2, 3);
	return 0;
}

在这里插入图片描述
传值需要注意的是:不能跳过传值,例如:

Func(1, ,3);//错误的

5.2.2 半缺省参数

void Func(int a, int b = 10, int c = 20)
{
	cout<<"a = "<<a<<endl;
	cout<<"b = "<<b<<endl;
	cout<<"c = "<<c<<endl;
}

注意

  1. 半缺省参数必须从右往左依次来给出,不能间隔着给。
  2. 缺省参数不能在函数声明和定义中同时出现。
//a.h
void Func(int a = 10);
// a.cpp
void Func(int a = 20)
{}
// 注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。
  1. 缺省值必须是常量或者全局变量
  2. C语言不支持(编译器不支持)

缺省参数应用场景

在进行数据结构的链表等可以更加高效。

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
namespace bit
{
	typedef struct Stack
	{
		int* a;
		int top;
		int capacity;
	}ST;
	void StackInit(bit::ST* ps, int defaultcp = 4)
	{
		ps->a = (int*)malloc(sizeof(int) * defaultcp);
		assert(ps->a);
		ps->top = 0;
		ps->capacity = defaultcp;
	}
}
int main()
{
	//不知道要插入多少个数据
	bit::ST stl;
	bit::StackInit(&stl);
	//知道要插入100个数据
	bit::ST st2;
	bit::StackInit(&st2, 100);
}

6.写在最后

那么C++入门上就到这里结束了。

在这里插入图片描述

相关文章:

  • 【面试题总结】分布式锦集
  • PostgreSQL执行计划获取与修改
  • 大幅提升CLIP图像分类准确率-Tip-Adapter
  • CCF- CSP历年认证考试题目链接+题解总结(持续更新)
  • 泛型、IO流 和 网络编程
  • 这些Java基础知识,诸佬们都还记得嘛(学习,复习,面试都可)
  • SSM《程序设计基础》课程答疑系统的设计与实现 毕业设计-附源码261620
  • R语言使用order函数按照两个数据列的值排序data.table数据(主变量升序排序、次变量降序排序)
  • Java Web 2 数据库 2.1 数据库相关概念 2.2 常见的关系型数据库管理系统 2.3 MySQL 数据库
  • DP58 红和蓝
  • grafana+prometheus+(采集节点)实现监控Linux服务器,JVM,Postgres
  • Unity 之 发布字节抖音小游戏
  • Web配置过滤器,Cookie对象的简单使用
  • 进程入门与PCB基础知识.
  • 【云原生】设备云之基于FlexManager的C#SDK开发案例代码
  • django开发-定时任务的使用
  • ES6 学习笔记(一)let,const和解构赋值
  • JAVA SE 6 GC调优笔记
  • JavaScript DOM 10 - 滚动
  • JavaScript对象详解
  • Java教程_软件开发基础
  • JS题目及答案整理
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • magento 货币换算
  • MobX
  • Terraform入门 - 3. 变更基础设施
  • 爱情 北京女病人
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 简析gRPC client 连接管理
  • 聊聊hikari连接池的leakDetectionThreshold
  • 马上搞懂 GeoJSON
  • 码农张的Bug人生 - 初来乍到
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 如何在 Tornado 中实现 Middleware
  • 收藏好这篇,别再只说“数据劫持”了
  • 追踪解析 FutureTask 源码
  • 06-01 点餐小程序前台界面搭建
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​520就是要宠粉,你的心头书我买单
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #### go map 底层结构 ####
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (2020)Java后端开发----(面试题和笔试题)
  • (分布式缓存)Redis分片集群
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)ObjectiveC 深浅拷贝学习
  • (转)大道至简,职场上做人做事做管理
  • (转)关于多人操作数据的处理策略
  • ***详解账号泄露:全球约1亿用户已泄露