• 【探索C++】C++对C语言的一些类的增强



            C++是在C语言的基础上进行了扩展和加强的编程语言,除了最典型的OOP(允许开发者使用类和对象来组织和管理代码)和三大特性,还有一些特点和增强。

    一、const关键字

            在C语言中,const关键字用于声明只读(read-only)变量,但它的只读性在编译期间是不强制执行的。这意味着虽然您可以使用const修饰一个变量,但仍然可以使用const指针去改变其值。这是C语言的一种弱约束。

    1. const int x = 10;
    2. int* ptr = (int*)&x; // 合法但不安全,ptr可以修改x的值
    3. *ptr = 20; // x的值被修改了

            而在C++中,const关键字更为严格它用于声明真正的常量。C++确保在编译期间对const进行强制执行,这意味着你不能使用普通指针指向const变量,也不能通过解引用方式间接修改其内容。只有使用const修饰的指针才能指向const变量。

    1. const int x = 10;
    2. const int* ptr = &x; // 合法,ptr是一个指向常量的指针
    3. int* ptr2 = (int*)&x; // 非法,编译器将报错
    4. *ptr2 = 20; // 非法,编译器将报错

    二、类型检测增强

            (1)类型必须一致才能相互赋值(除了本身可以进行隐式转换的类型之间)

            这是一种类型安全的规则,它确保了在赋值操作中,变量的数据类型必须匹配,除非涉及到可以进行隐式类型转换的情况。在C和C++中,类型必须明确,否则会引发编译器错误。例如,在C++中,不能将一个整数赋给一个字符串,除非进行适当的类型转换。


            (2) C语言中重复定义多个相同名字的全局变量是合法的,但是C++不允许

            这是C和C++之间的一个重要区别。在C语言中,可以在不同的源文件中多次定义相同名字的全局变量,编译器不会报错。这些全局变量在链接时会被合并。但是在C++中,这种操作是不允许的,会导致链接错误。C++要求每个全局变量只能定义一次,可以使用extern关键字来声明一个全局变量,然后在其他源文件中定义它。

            说到全局变量的定义,那就不得不提一下关于在C中我们可以在同一个工程下任意定义多个全局变量。

    1. // File1.c
    2. #include
    3. int globalVar = 42;
    4. void printGlobalVar() {
    5. printf("GlobalVar in File1.c: %d\n", globalVar);
    6. }
    1. // File2.c
    2. #include <stdio.h>
    3. int globalVar = 100; // 重复定义同名的全局变量
    4. void printGlobalVar() {
    5. printf("GlobalVar in File2.c: %d\n", globalVar);
    6. }

            但是在C++中是允许的,C++举例如下:

    1. // 在一个源文件中定义全局变量
    2. int globalVar = 42;
    3. // 在其他源文件中引用全局变量必须使用extern而不是再定义
    4. extern int globalVar;
    5. int main() {
    6. // 使用全局变量
    7. int x = globalVar;
    8. return 0;
    9. }

    三、枚举增强

            C语言中的枚举变量其实就是int,可以任意赋值,而C++的枚举变量只能赋值枚举值。

            C++引入了强类型枚举(enum class)以增强对枚举类型的类型安全性和可读性。这是对C语言中传统枚举的增强。下面是C++中枚举增强的几个要点。

            (1)强类型枚举(enum class): 强类型枚举引入了新的方式来定义枚举,它们在命名空间中创建了一个新的作用域,可以避免名称冲突,并且只能通过枚举的名称来访问枚举值。这提供了更好的类型安全性。

    1. enum class Color {
    2. Red,
    3. Green,
    4. Blue
    5. };
    6. Color myColor = Color::Red; // 强类型,只能通过Color::访问

            (2)默认底层类型: 强类型枚举默认的底层类型是int,但你可以显式指定底层类型。

    1. enum class Day : char {
    2. Monday,
    3. Tuesday,
    4. Wednesday,
    5. Thursday,
    6. Friday,
    7. Saturday,
    8. Sunday
    9. };

            (3)不会进行隐式类型转换: 强类型枚举不会隐式地转换为整数或其他类型,这减少了类型错误的可能性。

    1. enum class Month {
    2. January,
    3. February,
    4. March
    5. };
    6. int monthValue = static_cast<int>(Month::January); // 需要显式类型转换

            (4)枚举值作用域: 强类型枚举的值在其所属的枚举类的作用域内,不会污染全局命名空间。

    1. enum class Animal {
    2. Dog,
    3. Cat
    4. };
    5. Animal pet = Animal::Dog; // Animal是Animal枚举类的一部分

    四、三目运算符

            在C++中,三目运算符(也称为条件运算符) ? :  用于根据条件选择执行不同的操作。与C语言类似,与C语言不同的是,C++允许三目运算符的结果作为左值,这意味着你可以将其结果赋值给一个变量。这种特性在某些情况下可以帮助编写更简洁的代码。

    1. int a = 5;
    2. int b = 10;
    3. int result = (a > b) ? a : b; // 如果a > b,将a赋值给result,否则将b赋值给result

    五、 struct增强

            C语言的struct 定义一组变量的集合,C编译器并不认为这是一种新的类型,C++中的 struct 是一个新的类型的定义声明

            在C++中,struct和class都用于定义用户自定义数据类型,这是C语言中的struct的增强。尽管struct和class都可以用于定义类,但它们之间有一些关键的区别:

            (1)默认的访问控制:

    • 在C语言中,struct中的成员默认是public的,可以从任何地方访问。
    • 在C++中,structclass中的成员默认是private的,除非明确指定为public或其他访问修饰符


            (2)成员函数:

    • 在C语言中,struct中不能包含成员函数。
    • 在C++中,structclass都可以包含成员函数,允许在类内定义方法来操作成员数据。

            (3)默认继承权限:

    • 在C语言中,struct不能用于继承。
    • 在C++中,structclass都可以用于继承,但默认继承权限有所不同。在class中,继承默认是private的,而在struct中,继承默认是public的。

    1. // C++中的struct
    2. struct Person {
    3. std::string name;
    4. int age;
    5. void printInfo() {
    6. std::cout << "Name: " << name << ", Age: " << age << std::endl;
    7. }
    8. };
    9. // 继承自Person的struct,默认继承是public
    10. struct Student : Person {
    11. int studentId;
    12. };
    13. int main() {
    14. Person person;
    15. person.name = "Alice";
    16. person.age = 25;
    17. person.printInfo(); // 可以调用成员函数
    18. Student student;
    19. student.name = "Bob";
    20. student.age = 20;
    21. student.studentId = 12345;
    22. student.printInfo(); // 也可以调用Person的成员函数
    23. return 0;
    24. }

            在这个示例中,我们演示了C++中的 struct 可以包含成员函数,可以用于继承,并且默认继承权限是 public。这些特性使得C++中的 struct 在某些情况下更类似于class,但仍然保留了一些不同之处,如默认访问权限。

    六、 新增boo类型

            C++中的布尔类型(bool用于表示逻辑值,即真(true)或假(false)。布尔类型通常用于条件判断和控制程序的执行流程。以下是C++中布尔类型的介绍:

            布尔类型的声明: 在C++中,你可以声明一个布尔变量并将其初始化为truefalse,也可以将其用作函数的返回类型或参数类型。

    1. bool isTrue = true; // 声明一个布尔变量并初始化为true
    2. bool isFalse = false; // 声明一个布尔变量并初始化为false

            逻辑运算符: 布尔类型通常与逻辑运算符一起使用,例如&&(逻辑与)、||(逻辑或)和!(逻辑非)。这些运算符用于组合和操作布尔值。

    1. bool condition1 = true;
    2. bool condition2 = false;
    3. bool result1 = condition1 && condition2; // 逻辑与
    4. bool result2 = condition1 || condition2; // 逻辑或
    5. bool result3 = !condition1; // 逻辑非

            标准库: C++标准库中提供了一些与布尔类型相关的函数和类,例如头文件中的std::boolalpha操纵器,可以更改std::cout的输出格式以显示truefalse,而不是整数值1和0。

    1. #include <iostream>
    2. using namespace std;
    3. int main() {
    4. bool myBool = true;
    5. cout << boolalpha << myBool << endl; // 输出 "true",而不是 "1"
    6. return 0;
    7. }

    七、动态内存分配

            C++中的动态内存分配是一种非常重要的特性,用于在运行时动态分配和释放内存。下面对C++中的动态内存分配(new/delete)进行总结:

    1. 对比C和C++:

    • C语言使用malloc()free()函数来进行动态内存分配和释放。这些是函数。
    • C++语言引入了newdelete关键字,用于动态内存的分配和释放。

    2. 注意事项:

    • 配对使用:在使用new分配内存后,务必使用delete释放相应的内存,以避免内存泄漏和多次释放。
    • 避免交叉使用:不应将mallocdeletenewfree交叉使用,必须保持一致,以免出现未定义行为。
    • 主要用途:C++中,newdelete关键字的主要用途是在处理类对象指针时进行内存的动态分配和释放。

    3. 使用语法:

    • 使用new分配内存:使用new关键字来动态分配内存,并返回指向分配内存的指针。

    • 使用delete释放内存:使用delete关键字来释放之前分配的内存。

    1. 类型* 指针名 = new 类型;
    2. delete 指针名;
    1. int* myInt = new int; // 分配一个整数的内存
    2. *myInt = 42; // 向该内存写入值
    3. delete myInt; // 释放分配的内存

    注意事项:

    • 使用 newdelete 时要确保配对使用,否则可能导致内存泄漏或者程序崩溃。
    • 在 C++11 之后,推荐使用智能指针(如 std::unique_ptrstd::shared_ptr)来管理动态内存,以减少手动管理内存的错误和复杂性。

    在下面的示例中,首先使用 new 分配了一个整数对象和一个整数数组,然后使用 deletedelete[] 分别释放了它们占用的内存空间。

    1. #include <iostream>
    2. int main() {
    3. // 动态分配单个整数对象
    4. int* p = new int(42);
    5. // 动态分配整数数组
    6. int* arr = new int[10];
    7. for (int i = 0; i < 10; ++i) {
    8. arr[i] = i;
    9. }
    10. // 使用完后释放内存
    11. delete p;
    12. delete[] arr;
    13. return 0;
    14. }

            更多C/C++语言Linux系统数据结构ARM板实战相关文章,关注专栏:

       手撕C语言

                玩转linux

                        脚踢数据结构

                                系统、网络编程

                                         探索C++

                                                 6818(ARM)开发板实战

    📢写在最后

    • 今天的分享就到这啦~
    • 觉得博主写的还不错的烦劳 一键三连喔~
    • 🎉🎉🎉感谢关注🎉🎉🎉
  • 相关阅读:
    Word控件Spire.Doc 【邮件合并】教程(四):如何使用邮件合并合并图像值
    测试需求分析
    JavaWeb中的VUE快速入门
    Flink SQL Over 聚合详解
    训练卷积神经网络的意义,训练卷积神经网络模型
    java计算机毕业设计远程教学系统录屏源程序+mysql+系统+lw文档+远程调试
    如何用Stable Diffusion模型生成个人专属创意名片?
    spark源码的scala解析
    建立密切业务合作关系,供应商SRM系统助力企业做好新材料供应商品质管控
    【Node.js+koa--后端管理系统】设计标签创建、查询、接口 | 标签绑定到动态
  • 原文地址:https://blog.csdn.net/qq_64928278/article/details/132901708