【C++】入门(一)

news2024/7/6 0:48:19

在这里插入图片描述

前言:
本篇博客将带大家认识C++,熟悉基本语法


文章目录

  • 认识C++
    • C++的诞生与发展
    • C++ 在行业中的运用
  • 一、命名空间
    • 1.1 命名空间的定义
    • 1.2 命名空间的使用
    • 1.3 命名空间的访问
  • 二、C++输入&输出
    • 输出操作符 `<<`
    • 输入操作符 `>>`
    • 换行符和刷新输出缓冲区
    • 关键字 using
  • 三、缺省参数
    • 3.1 概念
    • 3.2 缺省参数分类
  • 四、函数重载
    • 概念
    • 函数重载的原理

认识C++

C++的诞生与发展

C++ 是由丹麦计算机科学家贝尔纳斯·斯特劳斯特博士(Bjarne Stroustrup)于20世纪80年代初期开发的。他在贝尔实验室工作时,对 C 语言进行了扩展,加入了OOP(object oriented programming:面向对象)思想,从而诞生了 C++。C++ 的名字中的 “++” 表示在 C 语言的基础上的一个增量,暗示这是对 C 的增强和扩展。因此:它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。

C++ 在其发展过程中经历了多个标准版本的发布,其中最早的标准是于1998年发布的 C++98,之后又有 C++03、C++11、C++14、C++17 和 C++20 等版本。每个版本都引入了新的特性和改进,使得 C++ 成为一个强大而灵活的编程语言。

" C with Classes" 是 C++ 的前身,这个术语最初用于描述贝尔纳斯·斯特劳斯特博士在开发 C++ 时的初期版本。C++ 最初是在 C 语言的基础上引入了一些面向对象编程的概念,而 “C with Classes” 就是这个过渡阶段的命名。

C++ 在行业中的运用

  1. 系统级编程: C++ 被广泛用于开发操作系统、驱动程序和其他系统级软件,因为它提供了对硬件的底层访问和高效的系统编程能力。

  2. 游戏开发: 许多游戏引擎和大型游戏项目都使用 C++。其高性能和底层控制使其成为游戏行业的首选语言之一。

  3. 嵌入式系统: C++ 被用于开发嵌入式系统,如智能家居设备、汽车控制系统等。它的效率和灵活性使其适用于资源受限的环境。

  4. 金融领域: 在金融行业,C++ 被广泛用于开发高性能的交易系统、风险管理工具和其他金融应用。

  5. 图形界面应用: C++ 被用于开发桌面应用程序、图形用户界面(GUI)和各种图形软件。

  6. 网络编程: C++ 的网络库和框架使其成为开发网络应用和服务器端程序的理想选择。

C++ 以其高性能、灵活性和底层控制能力,成为许多领域中首选的编程语言之一。


一、命名空间

命名空间(Namespace)是一种在C++中用于组织和封装代码的机制。它允许将一组相关的标识符(如变量、函数、类等)封装在一个逻辑单元中,目的是对标识符的名称进行本地化,以避免命名冲突或名字污染。命名空间可以被定义在全局作用域或其他命名空间内。

1.1 命名空间的定义

语法:

namespace 名称 {
    // 命名空间内的代码块
    // 变量、函数、类的声明和定义等
}
  1. 命名空间中可以定义变量/函数/类型

    namespace Namespace {
        // 变量
        int rand = 10;
    
        //函数
        int Add(int left, int right) {
    	    return left + right;
        }
    
        //类型
        struct Node {
    	       struct Node* next;
    	       int val;
        };
    }
    
  2. 命名空间可以嵌套

    // 外层命名空间
    namespace N1{
    	int a;
    	int Add(int left, int right){
    		return left + right;
    	}
    	
    	// 内层命名空间
    	namespace N2{
    		int c;
    		int Sub(int left, int right){
    			return left - right;
    		}
    	}
    }
    
  3. C++ 允许命名空间的逐渐定义,而多个定义会在编译时进行合并,确保同一命名空间内的内容是唯一的。
    在这个例子中,num3 命名空间的两个部分分别定义在不同的文件中,但它们最终会在编译时合并成为一个包含两个成员的命名空间。

    // 文件1.cpp
    namespace num3 {
        int rand = 3;
    }
    
    // 文件2.cpp
    namespace num3 {
        int y = 4;
    }
    

1.2 命名空间的使用

以下是一些常见的命名空间的使用场景和实践:

  1. 避免全局命名冲突: 命名空间允许将相关的标识符封装在一个独立的逻辑单元中,从而避免与其他代码中的相同名称的标识符发生冲突。这对于大型项目或多人协作的代码库非常重要。

    // 定义命名空间
    namespace MyNamespace {
        int myVariable;
        void myFunction();
        class MyClass { /* ... */ }
    }
    
  2. 组织和模块化代码: 命名空间使得代码更加模块化和易于组织。通过将相关的功能放置在同一个命名空间中,代码结构更加清晰,对于代码的理解和维护更加方便。

    // 在项目中的不同文件中使用同一个命名空间
    // File1.cpp
    namespace Math {
        int add(int a, int b);
    }
    
    // File2.cpp
    namespace Math {
        int subtract(int a, int b);
    }
    
  3. 防止全局污染: 将标识符限定在命名空间中,避免了全局命名空间的污染。这样有助于控制和隔离代码的影响范围。

    // 不使用命名空间的情况
    int globalVariable;
    
    // 使用命名空间
    namespace MyNamespace {
        int myVariable;
    }
    
  4. 版本控制: 在不同的版本中,可以使用命名空间来隔离和管理不同版本的功能或接口,以确保向后兼容性或易于升级。

    // Version 1
    namespace MyApp_v1 {
        void someFunction();
    }
    
    // Version 2
    namespace MyApp_v2 {
        void someFunction();
        void newFunction();
    }
    
  5. 解决命名冲突: 当使用第三方库或合作开发时,可能会遇到不同部分使用相同名称的情况。使用命名空间可以帮助解决这些命名冲突。

    // 第三方库的命名空间
    namespace ExternalLibrary {
        void commonFunction();
    }
    
    // 项目的命名空间
    namespace MyProject {
        void commonFunction();
        void myFunction();
    }
    

1.3 命名空间的访问

命名空间的成员可以通过作用域解析运算符 :: 进行访问。通过 :: 运算符,你可以指定要访问的命名空间的名称,从而使用其中的变量、函数或类等成员。

以下是一些命名空间访问的示例:

通过 MyNamespace::,我们可以访问命名空间 MyNamespace 中的变量、函数和类。这样的方式可以有效地避免全局命名冲突,同时使得代码更具可读性。

// 定义命名空间
namespace MyNamespace {
    int myVariable = 42;

    void myFunction() {
        // 函数定义
    }

    class MyClass {
        // 类定义
    }
}

int main() {
    // 访问命名空间中的变量
    int value = MyNamespace::myVariable;

    // 访问命名空间中的函数
    MyNamespace::myFunction();

    // 访问命名空间中的类
    MyNamespace::MyClass myObject;

    return 0;
}

通过 NS1:: 和 NS2:: 分别指定了要访问的命名空间,从而区分了两个同名的变量。

namespace NS1 {
    int x;
}

namespace NS2 {
    int x;
}

int main() {
    // 访问不同命名空间中的同名变量
    int value1 = NS1::x;
    int value2 = NS2::x;

    return 0;
}

当你有一个嵌套的命名空间结构时。在这个示例中,OuterNamespace 是外层命名空间,InnerNamespace 是内层命名空间。通过作用域解析运算符 ::,我们可以访问这两个命名空间中的变量。value1 获取了外层命名空间的变量值,而 value2 获取了内层命名空间的变量值。

// 外层命名空间
namespace OuterNamespace {
    int outerVariable = 42;

    // 内层命名空间
    namespace InnerNamespace {
        int innerVariable = 10;
    }
}

int main() {
    // 访问外层命名空间的变量
    int value1 = OuterNamespace::outerVariable;

    // 访问内层命名空间的变量
    int value2 = OuterNamespace::InnerNamespace::innerVariable;

    return 0;
}

二、C++输入&输出

C++ 中的输入和输出操作符是 <<(输出操作符)和 >>(输入操作符)。这些操作符用于在控制台或文件中进行输入和输出操作。

std 是C++标准库(Standard Library)的命名空间,coutcinendl 是C++标准库中命名空间std的对象,它们属于输入输出流相关的头文件 <iostream> 中的一部分。

输出操作符 <<

在C++中,<< 是输出流操作符,用于将右侧的数据插入到左侧的输出流中(通常是标准输出流,即屏幕)。std::cout 是标准输出流对象,<< 将数据输出到流中。多个 << 操作符可以串联使用,将多个数据输出到同一个流中。

#include <iostream>

int main() {
    int number = 42;
    std::cout << "The value of number is: " << number << std::endl;
    return 0;
}

输入操作符 >>

在C++中,>> 是输入流操作符,用于从流中读取数据。std::cin 是标准输入流对象,>> 从流中读取数据并存储在 number 变量中。

#include <iostream>

int main() {
    int number;
    std::cout << "Enter a number: ";
    std::cin >> number;
    std::cout << "You entered: " << number << std::endl;
    return 0;
}

换行符和刷新输出缓冲区

std::endl 是C++标准库中的一个操作符,用于表示换行符和刷新输出缓冲区。它实际上是一个函数模板,定义在头文件 中,并属于 std 命名空间。

使用 std::endl 可以在输出流中插入一个换行符,并确保输出缓冲区被刷新。刷新输出缓冲区是为了确保立即将输出内容显示在屏幕上,而不是等待缓冲区被填满或遇到显式的刷新操作。等效地,也可以使用 '\n' 来表示换行符。

#include <iostream>

int main() {
    int number = 42;

    // 使用 std::endl 插入换行符并刷新输出缓冲区
    std::cout << "The value of number is: " << number << std::endl;

    return 0;
}

关键字 using

使用 using 关键字可以展开命名空间中的标识符,使其在代码中更直接可用,而不需要显式加上命名空间的前缀。

以下是使用 using 展开命名空间的示例:

#include <iostream>

// 使用 using 展开命名空间
using namespace std;

int main() {
    // std::cout 可以直接使用为 cout
    cout << "Hello, World!" << endl;
    
    return 0;
}

需要注意的是,虽然 using namespace std; 提供了方便,但在大型项目中或与其他库集成时,可能会引入潜在的命名冲突。为了避免这些问题,一种更安全的方式是只使用需要的特定标识符,而不是整个命名空间。例如:

#include <iostream>

// 使用 using 展开需要的标识符
using std::cout;
using std::endl;

int main() {
    // 直接使用展开后的标识符
    cout << "Hello, World!" << endl;
    
    return 0;
}

三、缺省参数

3.1 概念

缺省参数(default parameters)允许在函数声明中为一个或多个参数指定默认值。这意味着在调用函数时,如果没有提供相应的参数值,将使用该参数的默认值

void Func(int a = 0){
	cout << a << endl;
}

int main(){
	Func();     // 没有传参时,使用参数的默认值
	Func(10);   // 传参时,使用指定的实参
	return 0;
}

3.2 缺省参数分类

函数的参数可以全部使用缺省参数,也可以部分使用缺省参数,实现全缺省参数和半缺省参数的效果。

全缺省参数:
printInfo 函数的所有参数都使用了缺省参数,可以在调用时不提供任何参数值,或者提供部分或全部参数值。

#include <iostream>

// 函数声明时全部使用缺省参数
void printInfo(int a = 1, int b = 2, int c = 3);

int main() {
    // 调用函数时不提供任何参数值,使用了所有参数的默认值
    printInfo();

    // 提供部分参数值
    printInfo(4);

    // 提供所有参数值,不使用默认值
    printInfo(7, 8, 9);

    return 0;
}

// 函数定义时也使用全部缺省参数
void printInfo(int a, int b, int c) {
    std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl;
}

半缺省参数:
半缺省参数必须从右往左依次来给出,不能间隔着

#include <iostream>

// 函数声明时部分使用缺省参数
void printInfo(int a, int b = 2, int c = 3);

int main() {
    // 调用函数时提供所有参数值,不使用默认值
    printInfo(7, 8, 9);

    // 提供部分参数值
    printInfo(4);

    // 调用函数时不提供任何参数值,使用了第一个参数的默认值
    printInfo();

    return 0;
}

// 函数定义时也使用部分缺省参数
void printInfo(int a, int b, int c) {
    std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl;
}

需要注意的是, 缺省参数应避免函数声明和定义中同时出现,当缺省参数在函数声明和定义中同时出现时,编译器会面临二义性的问题

如果缺省参数在函数声明和定义中同时出现:

  • 编译阶段:

    • 编译器首先会处理声明,其中包含缺省参数的值。这个信息在汇编代码中被保存。
    • 接着,编译器会处理定义,其中也包含缺省参数的值。
  • 链接阶段:

    • 链接器需要解析符号,即函数名和参数列表。但现在存在两个相同的函数符号,一个来自声明,一个来自定义。
    • 缺省参数的值在编译阶段已经确定,但由于声明和定义提供了相同的信息,链接器无法准确地选择应该使用哪个缺省参数的值。

因此,在声明和定义中同时出现缺省参数会导致链接阶段的二义性,编译器无法确定应该使用哪个值,从而引发错误。为了避免这种情况,建议在声明中指定缺省参数的值,而在定义中不再提供。这样,在链接阶段,编译器就能够使用声明中的默认值。


四、函数重载

概念

函数重载是指在同一个作用域内定义多个同名函数,但它们的参数列表 (包括参数的类型、顺序或数量)不同

#include <iostream>

using namespace std;

// 重载函数,按类型
void print(int x) {
    cout << "Integer: " << x << endl;
}

void print(double x) {
    cout << "Double: " << x << endl;
}

// 重载函数,参数个数不同
void display(int x) {
    cout << "Display Integer: " << x << endl;
}

void display(int x, double y) {
    cout << "Display Integer and Double: " << x << ", " << y << endl;
}

// 重载函数,参数顺序不同
void show(double x, int y) {
    std::cout << "Show Double and Integer: " << x << ", " << y << endl;
}

void show(int x, double y) {
    cout << "Show Integer and Double: " << x << ", " << y << endl;
}

int main() {
    // 函数按类型重载
    print(42);       // 调用第一个 print 函数
    print(3.14);     // 调用第二个 print 函数

    // 函数参数个数不同重载
    display(10);                   // 调用第一个 display 函数
    display(20, 3.5);              // 调用第二个 display 函数

    // 函数参数顺序不同重载
    show(2.5, 15);                 // 调用第一个 show 函数
    show(7, 4.2);                  // 调用第二个 show 函数

    return 0;
}

函数重载的原理

C++中使用名称修饰来实现函数重载。而在C语言中,并不使用名称修饰的方式,函数名是直接暴露的,因此C语言不支持函数重载

函数重载的编译阶段和链接阶段:

  1. 编译阶段:

    • 函数定义: 在源代码中,定义了多个同名但参数列表不同的函数,即进行函数重载。例如:

      void print(int x);
      void print(double x);
      
    • 名称修饰: 编译器在编译阶段根据函数的名称和参数列表生成唯一的名称修饰后的标识符。这个过程被称为名称修饰或符号修饰。

      • 例如,生成的标识符可能为 _Z5printi_Z5printd
    • 生成目标文件: 编译器将源代码编译成目标文件(通常是 .o 文件),其中包含了函数的名称修饰后的标识符。

  2. 链接阶段:

    • 符号表生成: 在链接阶段,链接器将汇总所有目标文件中的符号,创建一个符号表。符号表记录了函数和变量名与其对应的地址或标识符。

      • 符号表可能包含了 _Z5printi_Z5printd 这样的名称修饰后的标识符。
    • 解析函数调用: 当程序中有函数调用时,链接器查找符号表,尝试解析函数名。

      • 如果有一个唯一匹配的标识符,链接器确定正确的函数地址或标识符。
    • 写入可执行文件: 链接器将正确的函数地址或标识符写入最终的可执行文件中,确保在运行时能够正确调用相应的函数。

  3. 运行时:

    • 函数调用: 当程序运行时,根据函数调用,执行相应的函数。函数的具体实现取决于编译时和链接时确定的地址或标识符。

函数重载的过程涉及编译阶段和链接阶段:编译阶段中,编译器根据函数的名称和参数列表生成唯一的名称修饰后的标识符,汇总所有标识符并创建一个符号表;链接阶段中,链接器通过符号表解析函数调用,将正确的函数地址或标识符写入最终的可执行文件,确保在运行时能够正确调用相应的函数。


在这里插入图片描述
如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。

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

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

相关文章

C++入门学习(十二)字符串类型

上一节&#xff08;C入门学习&#xff08;十一&#xff09;字符型-CSDN博客&#xff09;中我们学到如何表示和使用一个字符串&#xff0c;本篇文章是字符串&#xff08;多个字符&#xff09;。 定义字符串主要有两种方式&#xff1a; 第一种&#xff1a; char str[] "…

openGauss学习笔记-203 openGauss 数据库运维-常见故障定位案例-修改索引时只调用索引名提示索引不存在

文章目录 openGauss学习笔记-203 openGauss 数据库运维-常见故障定位案例-修改索引时只调用索引名提示索引不存在203.1 修改索引时只调用索引名提示索引不存在203.1.1 问题现象203.1.2 原因分析203.1.3 处理办法 openGauss学习笔记-203 openGauss 数据库运维-常见故障定位案例-…

28、web攻防——通用漏洞SQL注入HTTP头XFFCOOKIEPOST请求

文章目录 $_GET&#xff1a;接收get请求&#xff0c;传输少量数据&#xff0c;URL是有长度限制的&#xff1b; $_POST&#xff1a;接收post请求&#xff1b; $_COOKIE&#xff1a;接收cookie&#xff0c;用于身份验证&#xff1b; $_REQUEST&#xff1a;收集通过 GET 、POST和C…

Web开发3:数据库使用

欢迎来到Web开发系列的第三篇&#xff01;今天我们将探讨如何在Web开发中使用数据库。数据库是存储和管理数据的重要工具&#xff0c;它在现代应用程序中起着至关重要的作用。无论是社交媒体应用、电子商务平台还是博客网站&#xff0c;数据库都是不可或缺的一部分。 什么是数…

基于DUP的网络聊天室

基于UDP的网络聊天室的使用&#xff08;select&#xff09;完成的服务器端 #include<head.h> typedef struct de {char name[10];struct sockaddr_in cin;struct de* next; }*linklist; //创建节点 linklist a_creat() {linklist p(linklist)malloc(sizeof(struct de));…

C++:基于C的语法优化

C&#xff1a;基于C的语法优化 命名空间命名空间域域作用限定符展开命名空间域 输入输出缺省参数全缺省参数半缺省参数 函数重载参数类型不同参数个数不同参数类型的顺序不同 引用基本语法按引用传递返回引用引用与指针的区别 内联函数autoauto与指针和引用结合 范围for循环nul…

统计灰度图像的灰度值分布并绘制

1、numpy方法 函数&#xff1a; numpy.histogram(a, bins10, rangeNone, normedNone, weightsNone, densityNone) 参数说明&#xff1a; a:输入数据数组&#xff1b;bins:指定统计的区间个数&#xff0c;可以是一个整数&#xff0c;也可以是一个数组&#xff0c;默认值为10…

续签KES证书

MiniO KES&#xff08;密钥加密服务&#xff09;是 MinIO 开发的一项服务&#xff0c;旨在弥合在 Kubernetes 中运行的应用程序与集中式密钥管理服务 &#xff08;KMS&#xff09; 之间的差距。中央 KMS 服务器包含所有状态信息&#xff0c;而 KES 在需要执行与获取新密钥或更新…

最小生成树(Java实现)

一、Prim算法 Prim算法基本思想为&#xff1a;从联通网络 N{V,E}中某一顶点 v0 出发&#xff0c;此后就从一个顶点在 S 集中&#xff0c; 另一个顶点不在 S 集中的所有顶点中选择出权值最小的边&#xff0c;把对应顶点加入到 S 集 中&#xff0c; 直到所有的顶点都加入到 S 集中…

RK3568平台 TinyAlsa集成第三方音频算法

一.tinyalsa介绍 ALSA&#xff08;Advanced Linux Sound Architecture&#xff09;是一个开源项目&#xff0c;涵盖了用户空间和内核空间对音频设备的操作接口&#xff0c;通过应用层使用alsalib可以实现对音频设备的控制 TinyAlsa是android推出的一个精简的ALSA库&#xff0c…

【Web实操08】实现一个导航效果,要求横向摆放,并且清除浮动

要实现图片的效果&#xff1a; 要利用浮动的知识点完成首页&#xff0c;电视&#xff0c;平板&#xff0c;家电&#xff0c;服务在一行导航栏剧中居中显示的功能&#xff0c;背景设置为灰黑色&#xff0c;导航栏下面是内容。 代码如下&#xff1a; <!DOCTYPE html> &l…

flink学习之窗口处理函数

窗口处理函数 什么是窗口处理函数 Flink 本身提供了多层 API&#xff0c;DataStream API 只是中间的一环&#xff0c;在更底层&#xff0c;我们可以不定义任何具体的算子&#xff08;比如 map()&#xff0c;filter()&#xff0c;或者 window()&#xff09;&#xff0c;而只是…

springboot集成COS对象存储

1.申请腾讯云存储桶 新建密钥&#xff08;后面配置要用到&#xff09; 2.编写工具类 此处使用工具类进行基本属性配置&#xff0c;也可选择在yml中配置 package com.sfy.util;import com.qcloud.cos.COSClient; import com.qcloud.cos.ClientConfig; import com.qcloud.cos.a…

开源堡垒机JumpServer本地安装并配置公网访问地址

文章目录 前言1. 安装Jump server2. 本地访问jump server3. 安装 cpolar内网穿透软件4. 配置Jump server公网访问地址5. 公网远程访问Jump server6. 固定Jump server公网地址 前言 JumpServer 是广受欢迎的开源堡垒机&#xff0c;是符合 4A 规范的专业运维安全审计系统。JumpS…

计算机服务器中了mallox勒索病毒怎么办,mallox勒索病毒解密数据恢复

企业的计算机服务器存储着企业重要的信息数据&#xff0c;为企业的生产运营提供了极大便利&#xff0c;但网络安全威胁随着技术的不断发展也在不断增加&#xff0c;近期&#xff0c;云天数据恢复中心接到许多企业的求助&#xff0c;企业的计算机服务器中了mallox勒索病毒&#…

IDEA2023.2 将普通项目转Maven项目

1、选中一个普通工程&#xff1a; 2、快捷键&#xff1a;ctrlshift a&#xff0c;搜索&#xff1a;Add Framework Support… 3、勾选maven&#xff0c;点击ok。

谁适合选择虚拟化

情况 前些天,有人问弄虚拟化怎么样: 还有一个群里,讨论了这事: 也弄了很多年了,虽然不算深入,毕竟,也是拼尽了全力,毕竟差不多7年的时光已经投入进去了,回头时,感觉没留下什么,有些十年技术一场空的感觉,真是应了虚拟化这几个字。 现在就大体说说这事: 先看看当前…

网络通信(Socket/TCP/UDP)

一、Socket 1.概念: Socket(又叫套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接协议,客户端的IP地址,客户端的端口,服务器的IP地址,服务器的端口。 一个Socket是一对IP地址…

DP专题17 单词拆分

本题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目&#xff1a; 思路&#xff1a; 由题意&#xff0c;根据题目意思&#xff0c;给出字符串 S&#xff0c;以及一个字符串数组&#xff0c;问字符串数组中 是否可以任取字符…

java中stream流进行遍历

在源代码转向加工到目标代码时&#xff0c;可以使用加工流代码加工 三种方式&#xff1a; 1.使用stream流的of方法 Stream.of(arr); 2.使用数组的Arrays.stream Arrays.stream(arr); 3.集合类&#xff0c;继承了Collection的.stream List<Strin…