• 【番外篇】C++语法学习笔记


    学习目标:C++的一些高级操作

    根据C++菜鸟教程自学的笔记,大家有想学习C++的话可以根据这个网站进行学习。这个推荐有一定基础的再去进行自学。新手的话还是建议直接看一些视频跟着学


    学习内容:

    1. 运算符重载

    说到C++中的运算符重载,首先要明确平时使用的加、减、乘、除、与、或、非、输入、输出、赋值、自增自减等这些运算符其实就是运算符重载的特殊情况。这些特殊情况只能对C++中的基础数据类型进行操作,如:“int”、“double”等。 而如果是用户自己定义的类型呢?比如自己定义的类的对象进行运算,想让这些自定义类型也进行加、减、乘、除这些操作,就只能进行运算符重载。

    (1).重载运算符的定义

    Box是声明的一个类:
          Box operator+(const Box& b)
          {
             Box box;
             box.length = this->length + b.length;
             box.breadth = this->breadth + b.breadth;
             box.height = this->height + b.height;
             return box;
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.文件读取和写入

    定义数据类型:#include

    写文件:
    ofstream outfile;
    outfile.open("file.dat", ios::out | ios::trunc );
    关闭文件outfile.close();
    
    读文件
    ifstream  afile;
    afile.open("file.dat", ios::out | ios::in );
    关闭文件infile.close();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3. 常量

    const关键字的定义:
    const int A = 1;
    此时a为常量,是不可以修改的
    
    #define 预处理器
    #define PI 3.1415926
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    宏定义的边际错误

    #include 
    using namespace std;
    
    #define cyy 10+1 
    
    int main()
    {
    	int area;
    	const int a = 1;
    	area = cyy * cyy;
    	cout << area<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    理想情况上面的代码输出的area值,应该为1111=121,但结果却为21
    原因是宏定义的编辑效应产生的错误,代码将area = cyy
    cyy看成了area = 10+1*10+1

    在定义常量或宏定义时,应用大写字母表示常量,这是很好的编程方式

    4. 变量的作用域

    全局变量:所有函数和代码块之外声明的变量,可以被任何代码中的函数访问,程序开始时创建,程序		结束时销毁。
    
    局部变量:局部变量是在函数内部定义的量
    
    
    块变量:块变量是在if,while中定义的
    
    使用外部链接的函数或全局变量,使用extern函数
    extern关键字,是在多个文件使用同一个变量时的声明方式
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    #include 
    int a = 1;
    void func()
    {
        int a = 10;
        {
            int a = 20;  // 块作用域变量
            std::cout << "块变量: " << a << std::endl;
        }
        std::cout << "局部变量: " << a << std::endl;
    }
    int main() {
        func();
        std::cout << "全局变量: " << a << std::endl;
        return 0;
    }
    
    输出结果:
    块变量: 20
    局部变量: 10
    全局变量: 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    5.存储类的关键字

    存储类主要的作用是在定义变量或函数的范围和生命周期。c++的程序中的存储类有:

    (1)register

    用于定义存储在寄存器而不是RAM中的变量,以便更快访问

    (2)static

    1. 限制变量的作用域在当前文件中,该变量只能在定义他的文件中使用
    2. static声明完静态变量后,在程序的整个执行期间都会一直存在,即使超出的声明他的函数的作用域

    (3) extern

    用于声明其他文件中定义的全局变量,也就是在B文件中使用A文件声明的全局变量

    6.字符串的使用

    C++中,有很多用于操作字符串的函数,这里记录一下
    在使用这些函数前,需声明一下:

    #include 
    
    • 1
    函数作用
    strcpy(s1,s2)复制字符串S2到S1中
    strcat(s1,s2)将S2链接到S1的末尾
    strlen(s1)返回字符串s1的长度
    strcmp(s1,s2)判断字符串s1和s2是否相同,相同返回0,s1s2返回值大于0
    strchr(s1,ch)返回一个指针,指向ch第一次出现在字符串s1的位置
    strstr(s1,s2)返回一个指针,指向字符串s1中,第一次出现字符串s2的位置

    7. 引用

    我在之前的学习引用的时候有一处一直搞不用,就是引用作为函数的参数,今天问了chatgpt一个问题后,豁然开朗

    问题:void swap(int& x, int& y);和void swap(int x, int y)的区别

    回答:

    1. 参数传递方式:第一个函数 void swap(int& x, int& y); 使用引用作为参数,而第二个函数 void swap(int x, int y); 使用值传递。
    2. 修改原变量:当调用 void swap(int& x, int& y); 函数时,函数内部可以直接修改传入的变量 x 和 y 的值。因为引用传递的是变量的地址,所以修改引用的值会影响到原变量。而当调用 void swap(int x, int y); 函数时,函数内部只能修改传入的副本变量 x 和 y 的值,不会影响原变量。
    3. 性能开销:使用引用传递可以避免对变量进行拷贝操作,提高代码的执行效率。而使用值传递需要进行值的拷贝,可能会产生较大的开销。

    代码案例

    1. 函数使用引用
    #include 
    using namespace std;
    int x = 10;
    int y = 20;
    void swap(int &x, int& y) {
    	int temp = x;
    	x = y;
    	y = temp;
    }
    int main() {
    	cout << "x:" << x << endl;
    	cout << "y:" << y << endl;
    	swap(x, y);
    	cout << "new_x:" << x << endl;
    	cout << "new_y:" << y << endl;
    }
    输出结果://x和y的值做了交换
    x:10
    y:20
    new_x:20
    new_y:10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    1. 函数不使用引用
    #include 
    using namespace std;
    int x = 10;
    int y = 20;
    void swap(int x, int y) {
    	int temp = x;
    	x = y;
    	y = temp;
    }
    int main() {
    	cout << "x:" << x << endl;
    	cout << "y:" << y << endl;
    	swap(x, y);
    	cout << "new_x:" << x << endl;
    	cout << "new_y:" << y << endl;
    }
    输出结果://x和y的值没做交换
    x:10
    y:20
    new_x:10
    new_y:20
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    总结:也就是说,当你想值使用传入变量的值时,使用值传递即可。但是当你想要修改传入变量的值时,使用引用传递,同时如果传入的参数过大,避免拷贝占用内存,使用引用传递也是很好的。

    8.结构

    C++中用户可以自定义可用的数据类型,这个叫结构体。

    定义结构,使用的是struct语句,其结构如下:

    struct Books{
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
    } book;
    
    
    可以对结构体进行声明和赋值
    Books Book1
    strcpy(Book1.title,"C++教程");
    Book1.bool_id = 1;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    9.抽象类和纯虚函数

    纯虚函数和抽象类之间是紧密关联的,抽象类是包含至少一个纯虚函数的类。纯虚函数没有具体的实现,只是提供了函数的接口。抽象类不能被实例化,只能用作其他类的基类来派生新的类。

    抽象类是一种特殊的类,不能被实例化,实例化抽象类将会报错。
    抽象类的定义:定义抽象类,需要抽象类中至少要有一个纯虚函数
    纯虚函数的定义: 纯虚函数通过在函数末尾使用=0来定义 virtual void pureVirtualFunction() = 0;

    一个纯虚函数的和抽象类的使用方法

    class Base {
    public:
        virtual void pureVirtualFunction() = 0; // 纯虚函数声明
    
        void normalFunction() {
            // 普通函数实现
            // ...
        }
    };
    
    class Derived : public Base {
    public:
        void pureVirtualFunction() override {
            // 派生类中重写纯虚函数,提供具体实现
            // ...
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    10. 虚函数和纯虚函数的区别

    虚函数纯虚函数
    声明函数前要加virtual关键字使用virtual 和“=0”声明
    派生类中是否需要重写随意必须重写

    11. 命名空间

    当你自定义的函数如zzy(),与另外一个函数库也有一个zzy()函数,编译器就无法判断你使用的时哪一个zzy()函数
    引入命名空间专门为了解决这个问题

    定义命名空间
    命名空间是需要定义的,这个目前我没有设计到,但其实就时把对应的函数放到命名空间这个大括号中即可
    namespace namespace_name{
    void func(){
    具体函数实现
    }
    }

    命名空间的使用
    using namespace std; 这个是最常见的命名空间
    如果不使用这个命令的话,很对c++的内置函数使用时就需要用“std::函数”的形式来使用

    12.模板

    13.lambda函数

    lambda函数是在C++ 11中新增的功能,广泛定义于需要定义短小的函数对象、算法和容器操作

    lambda的定义

    	[capture](parameters) -> return_type { body }
        auto sum = [](int a, int b) -> int {
        return a + b;
        };
    capture 是一个可选的捕获列表,用于在lambda函数内部访问外部变量。
    
    parameters 是参数列表,用于传递给lambda函数的参数。
    
    return_type 是返回类型,指定lambda函数的返回值类型。
    
    body 是函数体,包含lambda函数的具体实现逻辑。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    6-Dubbo架构设计与底层原理-服务导出源码分析(下)
    更新详情 | Flutter 3.22 与 Dart 3.4
    linux shell实现重启tomcat
    数据驱动的网络入侵检测:最新动向与研究趋势
    基于Java+SpringBoot+LayUI仓库管理系统
    探索请求头中的UUID的不同版本:UUID1、UUID3、UUID4和UUID5
    5.XSS-反射型(post)利用:获取cookie
    ON java8碎片(2)
    【带头学C++】基础知识[入门篇]----1.18 volatile强制访问内存
    matlab复制矩阵到c
  • 原文地址:https://blog.csdn.net/qq_43892462/article/details/132736953