【C++】C++ 的入门语法知识1

本文主要讲解C++语言的入门知识,包括命名空间、C++的输入与输出、缺省参数以及函数重载。


目录

1  C++的第一个程序

2  命名空间

1) 命名空间存在的意义

2) 命名空间的定义

3) 命名空间的使用

3  C++的输出与输入

1) C++中的输出

 2) C++中的输入

4  缺省参数

1) 缺省参数的定义

2) 缺省参数的使用

5  函数重载

1) 函数重载所解决的问题

2) 函数重载的条件

6  总结


1  C++的第一个程序

        C++语言是兼容C语言的,所以C语言的程序在C++语言的程序中依然适用,比如输出"hello world":

#include<stdio.h>int main()
{printf("hello world\n");return 0;
}

所以用C语言定义的文件只需要将后缀由 .c 变为 .cpp,那么这个文件就会由C语言变到了C++语言。虽然在C++文件中,C语言也可以兼容,但是C++语言有自己的一套输入输出。在C++语言中,输出"hello world"应该这样输出:

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

相信大家一上来学习C++语言,肯定是看不懂这段代码的,接下来我们依次来讲解。


2  命名空间

1) 命名空间存在的意义

        在 C 语言中,函数都是存在全局域的,然后如果在全局再定义一个同名变量,那么其是会发生命名冲突的,进而就会报错。如:

#include<stdio.h>
#include<stdlib.h>int rand = 10;int main()
{//编译报错:"rand"重定义printf("%d\n", rand);return 0;
}

在上面的程序中,首先包含了一个 stdlib.h 头文件,然后头文件里有一个 rand() 函数,包含了之后会将头文件的内容全部展开在全局域里面,之后又在全局定义了一个全局变量 rand,此时全局域有一个 rand() 函数,又有一个 rand 变量,此时就发生了命名冲突,printf 函数里面的 rand 不知道是全局变量还是函数,所以是会编译报错的。

        C++ 中为了解决命名冲突的问题,引入了一个命名空间的概念,命名空间上本质是定义出了一个独立的命名空间域,此域与全局域和局部域相互独立,不同域里面是可以定义相同名字的变量和函数的,此时就不会发生命名冲突了。


2) 命名空间的定义

        定义一个命名空间需要一个关键字 namespace,定义命名空间如下:

namespace 命名空间名
{}

首先加一个命名空间关键字 namespace,然后在后面加上想要定义的名字,后面跟一对{},然后就可以在里面定义函数或者变量了,如在 L 命名空间里定义一个 rand 变量:

namespace L
{int rand = 10;
}

命名空间存在的本质就是为了产生一个新的域,使其与全局域和局部域进行区分。此时 rand 变量就会存在在 L 命名空间里面,那么就不会与全局域中的 rand() 函数起冲突了,所以以下代码是可以编译通过的:

#include<stdio.h>
#include<stdlib.h>namespace L
{int rand = 10;
}int main()
{printf("%d\n", rand());return 0;
}

运行结果:

定义命名空间时,需要有几个注意事项

(1) C++中共有4个域:全局域、局部域、命名空间域、类域。域影响的是一个变量或者函数的查找规则(在C语言中默认现在局部域查找,局部域查找不到,再去全局域查找),所以命名就不会冲突了。但是全局域和局部域还会影响变量的生命周期(局部域里的变量出了函数就销毁了),命名空间域和类域不会影响生命周期

(2) namespace 只能定义在全局,也可以嵌套定义。

(3) C++ 标准库都放在一个名叫 std 的命名空间中

(4) 如果想要访问命名空间中的变量或者函数,需要一个操作符  ::(域访问限定符)。

(5) 不同文件的相同命名空间里的变量和函数会合并到一个命名空间中

(4) 域访问限定符: 

#include<stdio.h>
#include<stdlib.h>namespace L
{int rand = 10;int Add(int x, int y){return x + y;}struct Node{struct Node* next;int data;};
}int main()
{printf("%d\n", rand());//突破命名空间域访问,需要加::printf("%d\n", L::rand);printf("%d\n", L::Add(1, 2));//访问命名空间域中的类型是在名字前面加上::,而不是在类型前加上::struct L::Node* node = (struct L::Node*)malloc(sizeof(struct L::Node));return 0;
}

如果在 namespace 里面有自定义类型的话,是需要在名字前面加上 :: 的,而不是在 struct 前加 :: 的,因为命名空间限定的是名字,并不是类型(其实这里的Node就可以是类型了,只不过这里不叫结构体了,而是类,在类与对象章节会进行讲解)。

(2)   namespace 只能定义在全局,且可以嵌套定义

#include<stdio.h>
#include<stdlib.h>//命名空间可以嵌套定义
namespace L
{namespace T{int rand = 1;int Add(int x, int y){return x + y;}}
}int main()
{//访问的时候要依次突破命名空间域printf("%d\n", L::T::rand);printf("%d\n", L::T::Add(1, 2));return 0;
}

3) 命名空间的使用

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

a. 直接展开所有命名空间,需要使用 using 关键字,如:using namespace std。

b. 只将命名空间中的某个成员展开,也需要使用 using 关键字,比如展开 L 命名空间中的 rand 变量:using L::rand。

c. 指定命名空间访问,如使用 L 中的 rand 变量,L::rand。

当然,3种使用方式有好有坏, 平常练习的时候可以使用第一种方式,在项目中不推荐使用第一种方式,因为展开的所有的命名空间,就相当于将命名空间中的所有函数与变量暴露在全局,所以是非常容易出现命名冲突的;对于第二种方式,项目中经常访问的不存在冲突的成员推荐使用这种方式;在项目中最推荐使用的就是第三种方式了,第三种方式是最不会出现命名冲突的。

#include<stdio.h>namespace L
{int a = 0;int b = 10;
}void Test01()
{//指定命名空间访问printf("%d\n", L::a);
}//展开某个命名空间成员
using L::a;
void Test02()
{printf("%d\n", a);
}//展开所有命名空间
using namespace L;
void Test03()
{printf("%d\n", b);
}int main()
{Test01();Test02();Test03();return 0;
}

在上面那段代码里面,首先展开了 L 中的 a 成员,在后面又展开了 L 整个命名空间,这样看来,应该引入了两次 a 变量,是会发生命名冲突的,但是编译器是会对这种情况做特殊处理的,对于重复引入同一个变量的情况,是不会报错的。


3  C++的输出与输入

在讲解C++的输入与输出之前,我们先来简单了解一下 iostream 库以及 endl 函数。

iostream库:

iostream 是Input Output Stream(标准输入输出流库)的缩写,其中涉及了许多知识,包括继承等等,不过现在我们只需要了解 cin 和 cout 即可。

        通过上图,我们可以看到 iostream 中包含 cin、cout、cerr、clog,cin 来源于 isream,cout 来源于 ostream(其实 istream 和 ostream 是C++标准库中定义的类,cin 和 cout 是这两个类的对象),cin 主要用于输入,cout 主要用于输出

endl 函数:

通过上图可以看到,endl 其实是一个函数,其参数是一个 ostream类型对象,返回值也是一个 ostream 类型的引用(这里看不懂没关系,等学完引用与类和对象后自然就懂了);再通过下面的解释,可以看到其行为就等于调用了ostream类 os 对象的 put 函数,实际上就相当于输出了一个 '\n' 字符,也就是执行了一个换行。所以在C++中如果想要换行,我们一般不会使用 '\n' 转义字符,而会使用 endl 函数来执行换行操作。


1) C++中的输出

        在上面了解了 iostream 库与 endl 之后,我们知道了输出需要用到一个 ostream 类的对象 cout,所以在使用 cout 之前,我们需要先包含一个头文件 iostream,也就是引入 iostream 这个类,使得我们可以使用这个类实例化的一个对象 cout。在输出之前,我们还需要了解一个运算符叫做流插入运算符:<<。这个运算符的作用可以形象化的理解为会将要输出的对象流入 cout 中,然后 cout 帮你把对象打印在屏幕上。比如输出完 "hello world" 之后打印一个换行:

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

这里有一个需要注意的点,就是C++中的标准库都被封在了 std 的命名空间里面,要想使用C++中类和对象是需要展开命名空间 std 的,当然你也可以指定命名空间访问或者展开具体成员:

#include<iostream>//指定命名空间
int main()
{std::cout << "hello world";std::cout << std::endl;return 0;
}//展开具体成员
using std::cout;
using std::endl;
int main()
{cout << "hello world";cout << endl;return 0;
}

          但是C++中的 cout 与C语言中的 printf 最大的区别,也是我认为 cout 更加好用的一点是:cout 不用指定占位符,且可以连续输出不同的类型的对象(本质是函数重载,后面讲解完函数重载会更好理解)。如:

#include<iostream>using namespace std;int main()
{int x = 1;double y = 2.2;char ch = 'x';cout << "hello world" << ' ' <<  x << ' ' << y << ' ' << ch << endl;return 0;
}

运行结果:

hello world 1 2.2 x

 2) C++中的输入

        C++ 中的输入需要用到 istream 类的对象 cin,同样的在使用之间需要包含头文件 iostream 与展开命名空间 std、指定命名空间或者展开具体成员。与 cout 类似,在使用 cin 时,需要用到流提取操作符:>>,这个运算符可以形象化的理解为将屏幕中输入的值先交给 cin,cin 再通过 >> 将数据流入变量中,所以这里不需要对变量取地址的。同样,cin 也支持连续输入,如:

#include<iostream>using namespace std;int main()
{int x;double y;char ch;cin >> x >> y >> ch;cout << x << ' ' << y << ' ' << ch << endl;return 0;
} 

运行结果:

输入:1 2.2 x
输出:1 2.2 x

        cin 还可与 scanf 函数一样判断是否输入结束,但是 scanf 是通过返回值来判断的,如果读取成功,会返回读取成功的占位符个数,如果读取失败会返回 EOF,而 cin 是通过一个 operator bool() 的重载函数来实现的(这里可能难以理解,等后面仔细讲解完 iostream 类之后会比较容易理解),用法就是当读取成功时会返回 true,读取失败会返回 false。如:

#include<iostream>using namespace std;int main()
{int x = 0;while (cin >> x){cout << x << ' ';}return 0;
}

运行结果:

输入:1 2 3 4 ctrl + z
输出:1 2 3 4

4  缺省参数

1) 缺省参数的定义

        缺省参数也叫做默认参数,是在定义或者声明的时候给的参数的默认值。如果在调用参数的时候,不传递实参的话,就会默认使用缺省值,如果传递实参的话,就会使用传递的实参。

        缺省参数分为全缺省与半缺省参数。全缺省就是所有的形参都给缺省值,半缺省就是部分形参给缺省值。


2) 缺省参数的使用

在参数中给默认参数的时候,需要遵循以下语法规则:

(1) 缺省参数必须从右向左连续缺省,不能跳跃给缺省值。

(2) 调用带缺省参数的函数,必须从左向右依次给实参,不能跳跃传参。

(3) 函数声明与定义分离时,只能在声明给缺省值,不能在定义给缺省值

全缺省与半缺省: 

#include<iostream>using namespace std;//缺省参数只能从右向左连续缺省
//半缺省
void Func1(int a, int b = 10, int c = 20)
{cout << a << ' ' << b << ' ' << c << endl;
}//全缺省
void Func2(int a = 10, int b = 20, int c = 30)
{cout << a << ' ' << b << ' ' << c << endl;
}int main()
{//不传参时默认使用缺省值Func1(10);Func2();//传参只能由左向右依次传参,不能跳跃传参//错误的//Func1(10, , 20);//正确的Func1(10, 20);return 0;
}

运行结果:

输出:
10 10 20
10 20 30
10 20 20

 声明与定义分离,只能在声明时给缺省值:

#include<iostream>using namespace std;//只能在声明时给缺省值
void Func(int a = 10, int b = 20, int c = 30);//定义不能给
void Func(int a, int b, int c)
{cout << a << ' ' << b << ' ' << c << endl;
} int main()
{    Func();return 0;
}

运行结果:

输出:10 20 30

5  函数重载

        函数重载是C++语言中一个特别重要的语法,在以后的讲解的类和对象以及STL中经常使用。

1) 函数重载所解决的问题

        在 C语言中,同一作用域里是不能定义同名函数的,如要实现交换函数:

#include<stdio.h>void swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}void swap(double* x, double* y)
{double tmp = *x;*x = *y;*y = tmp;
}int main()
{int x = 10, y = 20;swap(&x, &y);double a = 1.1, double b = 2.2;swap(&a, &b);return 0;
}

这种情况在C语言里是会报错的,但是在C++里面就不会报错了,函数重载就是为了解决同名函数的问题。


2) 函数重载的条件

        两个函数如果想要构成函数重载,只需要一个条件,那就是两个函数参数不同,可以是参数个数不同或者类型不同。如:

#include<iostream>using namespace std;//1. 函数参数类型不同构成函数重载
int Add(int x, int y)
{cout << "Add(int x, int y)" << endl;return x + y;
}double Add(double x, double y)
{cout << "Add(double x, double y)" << endl;return x + y;
}//2. 函数参数个数不同构成函数重载
int Add(int x, int y, int z)
{cout << "Add(int x, int y, int z)" << endl;return x + y + z;
}//3. 函数参数类型顺序不同构成函数重载
void func(int x, double y)
{cout << "func(int x, double y)" << endl;
}void func(double x, int y)
{cout << "func(double x, int y)" << endl;
}int main()
{cout << Add(1, 2) << endl;cout << Add(1.1, 2.2) << endl;cout << Add(1, 2, 3) << endl;func(1, 2.2);func(2.2, 1);return 0;
}

运行结果:

输出:
Add(int x, int y)
3
Add(double x, double y)
3.3
Add(int x, int y, int z)
6
func(int x, double y)
func(double x, int y)

        函数重载,之所以能够构成函数重载,本质原因就是因为编译器能够通过参数去调用对应的函数,因而表现出了多态行为,所以不会因为命名相同而发生调用冲突。所以返回值不同是不构成函数重载的,因为编译器不知道去调用哪个函数

#include<iostream>using namespace std;//函数返回值不同不构成函数重载
void func()
{cout << "void func()" << endl;
}int func()
{cout << "int func()" << endl;
}int main()
{//编译器不知道去调用哪个函数func();return 0;
}

 有了函数重载的相关知识,大家看下面这两个函数构不构成函数重载呢?

#include<iostream>using namespace std;void func()
{cout << "func()" << endl;
}void func(int a = 10)
{cout << "func(int a = 10)" << endl;
}int main()
{func(1);func();return 0;
}

其实是构成函数重载的,因为两个 func 的参数个数不同,也就是参数不同,所以是可以构成函数重载的。但是有一个致命的缺陷,就是如果调用的是无参版本的 func 函数,编译器就会不知道去调用哪一个,因而会发生报错,这里的报错并不是因为函数重载的语法错误,而是因为编译器不知道去调用哪一个函数。

        但是遇到这种情况,我们一般都会选择使用下面有缺省值的版本,因为写上面那个函数,就是为了无参也能调用函数,而下面那个函数因为有缺省值,所以无参也是可以调用的,而且还有缺省值,所以会选择下面的版本。


6  总结

        以上我们讲解了C++中的一些基础的语法知识,虽然不是很难,但是是后面学习类和对象以及STL的基础,所以一定要认真学习,熟练掌握。当然我们也会结合后面具体的使用场景来继续加深对这些语法知识的理解。

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

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

相关文章

SpringBoot6-10(黑马)

JWT令牌简介&#xff1a;1.JWT全称:JSON Web Token(https://iwt.io/)定义了一种简洁的、自包含的格式&#xff0c;用于通信双方以json数据格式安全的传输信息。2.组成: >第一部分:Header(头)&#xff0c;记录令牌类型、签名算法等。例如:("alg":“HS256",“t…

智能制造场景195个术语的16个分类

说明&#xff1a;《智能制造典型场景参考指引&#xff08;2025年版&#xff09;》日前&#xff0c;由工信部办公厅正式发布&#xff0c;将成为众多制造型企业的工作纲领 1. 工厂数字化规划设计&#xff08;1.1&#xff09;&#xff1a;在电脑上用专业软件设计工厂布局、规划生产…

[论文阅读] 人工智能 + 软件工程 | 微信闭源代码库中的RAG代码补全:揭秘工业级场景下的检索增强生成技术

微信闭源代码库中的RAG代码补全&#xff1a;揭秘工业级场景下的检索增强生成技术 论文标题&#xff1a;A Deep Dive into Retrieval-Augmented Generation for Code Completion: Experience on WeChatarXiv:2507.18515 A Deep Dive into Retrieval-Augmented Generation for Co…

RabbitMQ—仲裁队列

上篇文章&#xff1a; RabbitMQ集群搭建https://blog.csdn.net/sniper_fandc/article/details/149312481?fromshareblogdetail&sharetypeblogdetail&sharerId149312481&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 目录 1 Raft一致性算法…

[2025CVPR-目标检测方向] CorrBEV:多视图3D物体检测

1. ​研究背景与动机​ 论文关注自动驾驶中相机仅有的多视图3D物体检测&#xff08;camera-only multi-view 3D object detection&#xff09;问题。尽管基于鸟瞰图&#xff08;BEV&#xff09;的建模近年来取得显著进展&#xff08;如BEVFormer和SparseBEV等基准模型&#xf…

oracle 数据库批量变更数据 将a表字段批量更新为b表字段

需求&#xff1a;将excel表中的数据批量更新到 taccoinfo表中vc_broker字段0、备份&#xff1a;create table taccoinfo0724 as select vc_custno ,vc_broker from taccoinfo 1、创建临时表&#xff1a; create table taccoinfo0724_1 as select vc_custno ,vc_broker from…

vim-xcode 项目常见问题解决方案

vim-xcode 项目常见问题解决方案 项目基础介绍 vim-xcode 是一个开源项目&#xff0c;旨在通过 Vim 编辑器与 Xcode 项目进行交互。该项目允许开发者在 Vim 中直接构建、测试和运行 Xcode 项目&#xff0c;从而提高开发效率。vim-xcode 主要使用 Vimscript 编写&#xff0c;并依…

个性化网页计数器

需要一个服务器环境来存放我们的计数器脚本和数据库。对于初学者来说&#xff0c;PHP和MySQL是一个不错的组合&#xff0c;因为它们易于学习且广泛应用。接下来&#xff0c;我们开始编写PHP脚本。这个脚本的主要任务是接收来自网页的请求&#xff0c;并将访问信息存储到数据库中…

详解力扣高频SQL50题之1683. 无效的推文【入门】

传送门&#xff1a;1683. 无效的推文 题目 表&#xff1a;Tweets ----------------------- | Column Name | Type | ----------------------- | tweet_id | int | | content | varchar | ----------------------- 在 SQL 中&#xff0c;tweet_id 是这个表的主键。 content 只…

Spring Boot与Python的联动:实战案例解析

目录一、背景与需求二、技术准备2.1 Spring Boot 基础2.2 Python 环境搭建三、基于 RESTful API 的调用3.1 创建 Python Flask 应用3.2 创建 Spring Boot 应用3.3 测试与验证四、通过 ProcessBuilder 调用 Python 脚本4.1 创建 Python 脚本4.2 Spring Boot 中调用脚本4.3 注意事…

力扣刷题(第九十七天)

灵感来源 - 保持更新&#xff0c;努力学习- python脚本学习密钥格式化解题思路移除原字符串中的所有破折号&#xff0c;并将小写字母转换为大写。从后向前遍历处理后的字符串&#xff0c;每 K 个字符为一组。最后将各组逆序拼接&#xff0c;并用破折号分隔。class Solution:def…

ESP32入门实战:PC远程控制LED灯完整指南

引言&#xff1a;物联网远程控制基础 远程控制是物联网应用的基础功能之一&#xff0c;通过ESP32实现PC远程控制LED灯不仅是一个经典入门项目&#xff0c;更是理解网络通信、嵌入式开发和物联网交互的绝佳实践。本文将详细介绍如何通过WiFi和UDP协议&#xff0c;从零开始构建一…

主流摄像头协议及其开源情况,GB/T 28181协议介绍

一、主流摄像头协议及开源情况 1. RTSP&#xff08;Real Time Streaming Protocol&#xff09; 技术特性&#xff1a;基于TCP/UDP的实时流传输协议&#xff0c;支持双向通信&#xff08;如暂停、播放控制&#xff09;。应用场景&#xff1a;摄像头实时监控、视频点播系统。开源…

「iOS」——RunLoop学习

底层学习iOS--RunLoop学习RunLoop的概念RunLoop与线程的关系RunLoop的结构ModeObserverTimerSourceRunLoop 执行流程RunLoop 的应用1.AutoreleasePool是什么时候释放的2.触控事件的响应3.刷新界面4.线程保活小知识mach Port**Toll-Free Bridging&#xff08;对象桥接&#xff0…

从零构建 Node20+pnpm+pm2 环境镜像:基于 Dockerfile 的两种方案及持久化配置指南

前言&#xff1a;在Node.js项目部署中&#xff0c;环境一致性和服务自动恢复是运维的核心需求。无论是本地开发还是生产部署&#xff0c;使用Docker封装Node20、pnpm&#xff08;高效包管理&#xff09;和pm2&#xff08;进程守护&#xff09;环境&#xff0c;能避免“本地能跑…

【Python机器学习】4.3. 模型优化

喜欢的话别忘了点赞、收藏加关注哦&#xff08;关注即可查看全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 4.3.1. 实战中会遇到的问题 首先看一个例子&#xff1a; 根据任检测数据x1x_1x1​、x2x_2x2…

Impact rating 影响等级定义(学习笔记)

影响等级可以通过四个方面定义&#xff0c;包含安全性safety&#xff0c;经济型financial&#xff0c;操作性operational&#xff0c;和私密性privacy 即[S,F,O,P]这四个方面。每个方面又可以定义四个不同的等级&#xff0c;包含severe&#xff08;严重的&#xff09;&#xff…

同花顺前端潜在面试题目与答案

潜在面试题目与答案 以下是根据您提供的“岗位职责”和“岗位要求”整理出的潜在面试题目和参考答案。请注意&#xff0c;这些答案仅供参考&#xff0c;您需要根据自己的实际经验和理解进行更详细和个性化的阐述。 一、基础技术知识&#xff08;Vue/前端工程化/HTML/CSS/JS&…

J2EE模式---组合实体模式

组合实体模式基础概念组合实体模式&#xff08;Composite Entity Pattern&#xff09;是一种企业级设计模式&#xff0c;属于 J2EE 模式的一种&#xff0c;其核心思想是将多个实体对象组合成一个更高层次的对象&#xff08;组合实体&#xff09;&#xff0c;以简化客户端与这些…

基于CloudBase+React+CodeBudddy的云上智能睡眠应用开发实践

本文详细记录了如何利用CloudBase云开发平台、React前端框架和CodeBudddy智能编程技术栈&#xff0c;构建一个云端智能睡眠监测与分析系统。通过完整的项目实践&#xff0c;探索AIoT时代健康管理应用的开发范式。一、智能睡眠监测&#xff1a;云时代的健康守护者在快节奏的现代…