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

【C++】新手入门指南(上)

文章目录

一、C++的第一个程序

二、命名空间

1.namespace的价值

2.namespace的定义

3、命名空间使用

三、C++输入&输出

四、缺省参数

五、函数重载

总结


一、C++的第一个程序

C++兼容C语言绝大多数的语法,所以C语言实现的hello world依旧可以运行,C++中需要把定义文件代码后缀改为.cpp,vs编译器看到是.cpp就会调用C++编译器编译,linux下要用g++编译,不再是gcc
// test.cpp
#include<stdio.h>
int main()
{printf("hello world\n");return 0;
}
当然C++有一套自己输入输出,严格说C++版本的hello world应该是这样写的。
// test.cpp
#include<iostream>
using namespace std;
int main()
{
// 这⾥的std cout等我们都看不懂,没关系,下⾯我们会依次讲解cout << "hello world\n" << endl;return 0;
}

二、命名空间

1.namespace的价值

在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染, namespace关键字 的出现就是针对这种问题的。
C语言项目如下面程序这样的命名冲突是普遍存在的问题:
#include<stdlib.h>
int rand = 10;
int main()
{printf("%d\n", rand);// 编译报错: “rand”: 重定义;以前的定义是“函数”return 0;
}

会出现编译报错:“rand”: 重定义;以前的定义是“函数”。这是因为在全局定义一个变量,而在编译器的库中找到一个和全局变量一样的名字,引起了命名冲突。所以,C++引入一个语法为命名空间用来解决 函数与函数之间的命名冲突 和 函数与库的命名冲突 等问题。

解决方法:

#include<iostream>
#include<stdlib.h>
namespace LH
{//定义变量int rand = 10;
}int main()
{printf("%d\n", LH::rand);//这里指定YY命名空间中randreturn 0;
}

在这里出现一个新的知识点 域作用限定符:: ,其作用是指定作用域。比如上面 LH 是一个命名空间,而 rand 定义在命名空间中,要打印 rand 就要指定 rand  LH命名空间中才能准确找到,域作用限定符就是用来指定LH的命名空间域中找rand

2.namespace的定义

1.定义命名空间的结构: 后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
#include<stdlib.h>
namespace LH
{//定义变量int rand = 10;//定义函数int Add(int x, int y){return x + y;}//定义结构体struct Node{struct Node* next;int val;};
}

2.namespace本质是定义出一个域:这个域跟全局域各自独立,不同的域可以定义同名变量,所以下面的rand不在冲突了。

在C语言中,只有全局域和局部域,因此在不同的域不能定义同名变量;为了改变这一缺点,C++就引用命名空间,而命名空间是一个域,在这个域里可以和全局域定义同名变量,因为是俩个不同的域不会起冲突,在命名空间定义的变量的生命周期是全局。

#include<iostream>
#include<stdlib.h>
namespace LH
{//定义变量int rand = 10;
}int main()
{printf("%p\n", rand);//这里访问全局rand函数的指针,打印出来是地址printf("%d\n", LH::rand);//这里指定LH命名空间中randreturn 0;
}
3.C++有四个域分别为函数局部域,全局域,命名空间域,类域:
域影响的是编译时语法查找一个变量/函数/类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的⽣命周期,命名空间域和类域不影响变量⽣命周期。
4.namespace只能定义在全局,还可以嵌套定义
一个命名空间可以嵌套多个定义,但在访问的时候需要指定两层命名空间,才能准确找到rand的位置。
//嵌套定义:
namespace LH
{namespace cy{int rand = 1;}namespace fff{int rand = 2;}
}int main()
{//访问:要指定俩层命名空间,如下printf("%d\n", LH::cy::rand);printf("%d\n", LH::fff::rand);return 0;
}

5.项目文件中namespace关键字定义命名空间出现重复命名,编译器中会认为是用同一个namespace。

6.C++标准库都放在一个叫std(standard)的命名空间中:为了避免出现C++标准库与命名空间起冲突,把C++标准库放在std的命名空间中。可以去std的命名空间中访问C++标准库。

3、命名空间使用

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

1.指定命名空间访问

在项目中推荐使用这个方法。想访问命名空间的成员只需指定一下即可。

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

2.using将展开命名空间中全部成员

在项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
namespace Ti
{int rand = 20;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}//使用using将命名空间中变量rand,函数Add进行展开
using namespace Ti;
int main()
{printf("%d\n", Ti::rand);printf("%d\n", Ti::Add(4, 20));return 0;
}

3.using将命名空间中某个成员展开

在项目中经常访问的不存在冲突的成员推荐这种方式。如果不频繁调用就可使用这个。

namespace Ti
{
int rand = 20;int Add(int left, int right)
{return left + right;
}struct Node
{struct Node* next;int val;
};
}//使用using将命名空间中函数Add进行展开
using namespace Ti;
int main()
{printf("%d\n", Ti::rand);//频繁调用Add函数printf("%d\n", Ti::Add(4, 20));printf("%d\n", Ti::Add(62, 3));printf("%d\n", Ti::Add(62, 3));printf("%d\n", Ti::Add(62, 3));printf("%d\n", Ti::Add(62, 3));printf("%d\n", Ti::Add(62, 3));return 0;
}

三、C++输入&输出

<iostream> 是 Input Output Stream 的缩写,是标准的输入、输出流库,定义了标准的输入、输出对象。
std::cin 是 istream 类的对象,它主要面向窄字符(narrow characters(of type char))的标准输入流。

std::cout 是 ostream 类的对象,它主要面向窄字符的标准输出流。

std::endl 是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区。
<<是流插入运算符,>>是流提取运算符
using namespace std;
int main()
{int i = 1;double d = 3.4;//输出cout << i << endl;cout << d << endl;cout << i << ' ' << d << endl;cout << "hello world" << endl;//输入的作用cin >> i >> d;cout << i << ' ' << d << endl;return 0;
}

注:
1.使用C++输入输出更方便,不需要手动指定格式,C++的输入输出可以自动识别变量类型(本质是通过函数重载实现的)

2.cout/cin/endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以可以用命名空间来使用C++标准库
3.在日 常练习中我们可以using namespace std,实际项目开发中不建议using namespace std;

4.这里我们没有包含<stdio.h>,也可以使用printf和scanf,在包含<iostream>间接包含了

四、缺省参数

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)
using namespace std;
void Func(int a = 0)
{cout << a << endl;
}
int main()
{Func();//没有传参时,使用参数的默认值Func(20);//传参时,使用指定的实参return 0;
}

全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。在C++规定带缺省参数的函数调用,必须从左到右依次给实参,不能跳跃给实参。

//全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{cout << "a=" << a << endl;cout << "b=" << b << endl;cout << "c=" << c << endl;
}
//半缺省
void Func2(int a, int b = 10, int c = 20)
{cout << "a=" << a << endl;cout << "b=" << b << endl;cout << "c=" << c << endl;
}int main()
{//虽然Func1函数给了默认值,但是可以在主函数里改的//Func1();//10 20 30//Func1(1);//1 20 30//Func1(1, 2);//1 2 30//Func1(1, 2, 3);//1 2 3//Func1(1,,3);这种写法不行,不能跳,必须要按顺序来Func2(100);//100 10 20Func2(100, 200);//100 200 20Func2(100, 200, 300);//100 200 300return 0;
}

函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,会造成空间浪费,因此只能在声明中确定缺省值。

五、函数重载

在C语言中, 不能同时出现函数名一样的函数,即使函数类型不同也不能,编译会报错;为了解决这一问题C++提出 函数重载 C++支持在同一作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者 类型不同。
using namespace std;//1.参数类型不同
int Add(int left, int right)
{return left + right;
}double Add(double left, double right)
{return left + right;
}//2.参数个数不同
void f()
{cout << "f()" << endl;
}
void f(int a)
{cout << "f(int a)" << endl;
}//3.参数类型顺序不同
void f(int a, int b)
{cout << "f(int a,int b)" << endl;
}void f(char b, int a)
{cout << "f(char b,int a)" << endl;
}//
int main()
{cout << Add(10, 20) << endl;cout << Add(3.2, 4.2) << endl;f();f(10);f(10,'a');f('a', 10);return 0;
}


总结

非常感谢大家阅读完这篇博客。希望这篇文章能够为您带来一些有价值的信息和启示。如果您发现有问题或者有建议,欢迎在评论区留言,我们一起交流学习。

http://www.xdnf.cn/news/480.html

相关文章:

  • Spring AI 开发 - 快速入门
  • 让机器学习更透明:使用 Python 开发可解释性模型工具包
  • 检索增强生成(RAG)系统的技术演进、核心架构与优化实践
  • Python语法系列博客 · 第5期[特殊字符] 模块与包的导入:构建更大的程序结构
  • 验证Kubernetes的服务发现机制
  • 【信息系统项目管理师】高分论文:论信息系统项目的干系人管理(ERP运营管理系统)
  • 大模型如何重塑未来:从技术突破到商业应用
  • leetcode0113. 路径总和 II - medium
  • Linux系统:详解进程等待wait与waitpid解决僵尸进程
  • cJSON_Print 和 cJSON_PrintUnformatted的区别
  • MinnowBoard MAX单板UEFI BIOS代码编译教程
  • 使用AOP完成添加日志
  • 【AI提示词】IT专家顾问
  • 文件上传及验证绕过漏洞
  • Delphi 常用关键字收录
  • 基础智能体的进展与挑战第 6 章【情绪建模】
  • Python遥感开发之Hurst指数的实现
  • Zookeeper的典型应用场景?
  • Keil MDK中禁用半主机(No Semihosting)
  • 齐次坐标变换+Unity矩阵变换
  • 【Tauri2】026——Tauri+Webassembly
  • 代谢组数据分析(二十四):基于tidymass包从质谱原始数据到代谢物注释结果的实践指南
  • vue3 watch和watchEffect 的用法和区别
  • 计算机视觉算法实现——智能座椅坐姿识别
  • 基于GRPO将QWEN训练为和deepseek一样的推理模型!
  • linux kernel irq相关函数详解
  • 国产的 Java Solon v3.2.0 发布(央企信创的优选)
  • Day10【基于encoder- decoder架构实现新闻文本摘要的提取】
  • 第3章 垃圾收集器与内存分配策略《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》
  • 从0开发一个unibest+vue3项目,使用vscode编辑器开发,总结vue2升vue3项目开始,小白前期遇到的问题