• C++关键词探索:理解变量、函数参数、函数返回值以及类成员函数的修饰符


    在C++编程中,我们经常会遇到一些关键词,它们可以用来修饰变量、函数参数、函数返回值以及类的成员函数。这些关键词包括 const、static、volatilemutablesignedunsignedlongshortvirtualexplicitinlinefriend。让我们一起来深入理解一下这些关键词。

    const关键词

    const是一个常量修饰符,它可以用来修饰变量、函数参数、函数返回值以及类的成员函数。

    • 修饰变量:当const修饰一个变量时,表示这个变量的值是不能被修改的。例如:
    const int a = 10;  // a 是一个常量,不能被修改
    
    • 1
    • 修饰函数参数:当const修饰一个函数参数时,表示这个参数在函数内部是不能被修改的。这对于引用和指针参数特别有用,因为它可以防止函数意外地修改参数的值。例如:
    void func(const int& a) {
        // 在这个函数中,a 是不能被修改的
    }
    
    • 1
    • 2
    • 3
    • 修饰函数返回值:当const修饰一个函数返回值时,表示这个返回值是不能被修改的。这对于返回引用或者指针特别有用,因为它可以防止函数的调用者修改返回值。例如:
    const int& func() {
        static int a = 10;
        return a;  // 返回一个常量引用,调用者不能通过这个引用来修改 a 的值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 修饰类的成员函数:当const修饰一个类的成员函数时,表示这个成员函数不能修改类的任何成员变量(除非这些变量被声明为mutable)。这对于需要保证对象状态不变的操作非常有用。例如:
    class MyClass {
    public:
        void func() const {
            // 这是一个 const 成员函数,它不能修改类的任何成员变量
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在C++中,const关键词用于声明一个变量或函数参数为只读,表示其值在初始化后不能被修改。一旦为const变量分配了一个值,就不能改变它,任何试图修改它的尝试都会导致编译错误。

    static关键词

    static是一个存储类别说明符,它可以用来修饰全局变量、局部变量、类成员变量以及类成员函数。

    • 修饰全局变量:当static修饰一个全局变量时,表示这个全局变量只能在本文件中使用。这可以防止其他文件通过外部链接来访问这个全局变量。
    static int a = 10;  // a 是一个静态全局变量,只能在本文件中使用
    
    • 1
    • 修饰局部变量:当static修饰一个局部变量时,表示这个局部变量的生命周期是全局的,即它会在程序运行过程中一直存在。并且它们只会被初始化一次。
    void func() {
        static int a = 0;  // a 是一个静态局部变量,它的生命周期是全局的
        a++;
        cout << a << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 修饰类成员:当static修饰一个类的成员变量时,表示这个成员变量是类的所有对象共享的。当static修饰一个类的成员函数时,表示这个成员函数不依赖于任何对象就可以被调用。
    class MyClass {
    public:
        static int a;  // a 是一个静态成员变量,所有 MyClass 的对象都共享这个变量
    
        static void func() {
            // 这是一个静态成员函数,它不依赖于任何对象就可以被调用
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注意:static关键词只用于在类定义中声明静态成员,而不用于该静态成员的定义。例如:

    class X { 
        static int n; 
    }; // 声明(使用'static')
    
    int X::n = 1; // 定义(不使用'static')
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里,n是类X的静态成员。

    总结起来说,虽然 **const ** 和 **static ** 在语法上有一些微小的区别,但它们都可以帮助我们编写出更安全、更易于理解和维护的代码。

    volatile关键词

    当我们使用volatile关键词修饰一个变量时,它告诉编译器这个变量可能会被意想不到地改变,因此编译器不应该对这个变量进行优化。这在处理某些特殊的情况(如多线程或硬件交互)时非常有用。

    volatile int flag = 0;
    
    • 1

    在这个例子中,我们告诉编译器 flag 变量可能会被意想不到地改变,因此编译器不应该对它进行优化。

    mutable关键词

    当我们使用 mutable 关键词修饰一个类的成员变量时,即使在一个 const 成员函数中,我们也可以修改这个 mutable 成员的值。

    class MyClass {
    public:
        mutable int a;
    
        void func() const {
            a = 10;  // 即使在 const 成员函数中,我们也可以修改 mutable 成员的值
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这个例子中,我们定义了一个 mutable 成员 a。即使在 const 成员函数 func() 中,我们也可以修改 a 的值。

    signed和unsigned关键词

    当我们使用 signedunsigned 关键词修饰一个整型变量时,它们分别表示这个变量是有符号的还是无符号的。

    signed int a = -10;  // a 是一个有符号整数
    unsigned int b = 10;  // b 是一个无符号整数
    
    • 1
    • 2

    在这个例子中,我们定义了一个有符号整数 a 和一个无符号整数 b.

    long和short关键词

    当我们使用 longshort 关键词修饰一个整型或浮点型时,它们分别表示增加或减少这个类型的长度。

    long long a = 10000000000LL;  // a 是一个长整型
    short b = 10;  // b 是一个短整型
    
    • 1
    • 2

    在这个例子中,我们定义了一个长整型 a 和一个短整型 b.

    virtual关键词

    当我们使用 virtual 关键词修饰一个类的成员函数时,它表示这个函数是虚函数,可以被子类重写。

    class Base {
    public:
        virtual void func() {
            cout << "Base::func()" << endl;
        }
    };
    
    class Derived : public Base {
    public:
        void func() override {
            cout << "Derived::func()" << endl;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    virtual关键词告诉编译器一个非静态成员函数是虚拟的,并支持动态分派。
    它只能出现在非静态成员函数的初始声明中(即在类定义中声明时)。
    虚拟函数是可以在派生类中重写其行为的成员函数。
    与非虚拟函数相反,即使没有编译时关于类实际类型的信息,重写行为也会保留

    在这个例子中,基类 Base 的成员函数 func() 被声明为虚函数。因此,在派生类 Derived 中,我们可以重写这个函数。

    explicit关键词

    当我们使用 explicit 关键词修饰一个构造函数时,它阻止编译器进行非预期的类型转换。在C++中,如果一个类有一个接受单一参数的构造函数,那么这个构造函数就可能被编译器用作隐式类型转换。这种转换可能会导致一些非预期的结果。例如:

    class MyClass {
    public:
        MyClass(int a) {
            // ...
        }
    };
    
    void func(MyClass obj) {
        // ...
    }
    
    int main() {
        func(10);  // 隐式类型转换
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这个例子中,我们定义了一个类 MyClass, 它有一个接受单一参数的构造函数。然后,我们定义了一个函数 func, 它接受一个 MyClass 对象作为参数。在 main 函数中,我们调用了 func 函数,并传入了一个整数。由于 MyClass 有一个接受整数的构造函数,因此编译器会自动地将这个整数转换为 MyClass 对象。这就是所谓的隐式类型转换。

    然而,在某些情况下,我们可能不希望编译器进行这种隐式类型转换,因为它可能会导致一些非预期的结果。这时,我们就可以使用 explicit 关键词来修饰构造函数,阻止编译器进行隐式类型转换。例如:

    class MyClass {
    public:
        explicit MyClass(int a) {
            // ...
        }
    };
    
    void func(MyClass obj) {
        // ...
    }
    
    int main() {
        func(10);  // 编译错误:无法将 int 转换为 MyClass
        func(MyClass(10));  // 正确:显式类型转换
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这个例子中,由于构造函数被声明为 explicit, 因此编译器不会自动地将一个整数转换为 MyClass.
    总结起来说,使用 **explicit ** 关键词可以防止编译器进行非预期的隐式类型转换,从而使我们的代码更加安全和易于理解。

    inline关键词

    当我们使用 inline 关键词修饰一个函数时,它建议编译器将函数体直接插入到每个调用处,以减少函数调用的开销。

    inline int add(int a, int b) {
        return a + b;
    }
    
    • 1
    • 2
    • 3

    在这个例子中,我们建议编译器将 add 函数的函数体直接插入到每个调用处(这个过程称为扩展),然后编译整个代码。如果函数很小,使用内联函数可能会提高效率,因为它们消除了与函数调用相关的开销。

    friend关键词

    当我们使用 friend 关键词修饰一个非成员函数或其他类时,它允许这个函数或类访问当前类的私有和保护成员。

    class MyClass {
    private:
        int a;
    
        friend void func(MyClass& obj);
    };
    
    void func(MyClass& obj) {
        obj.a = 10;  // 可以访问 MyClass 的私有成员
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这个例子中,我们允许非成员函数 func 访问 MyClass 的私有成员。
    也就是说,friend关键词在C++中可以用于共享之前隐藏的类的信息。例如,一个类的私有成员对其他所有类都是隐藏的,除非通过getter或setter进行修改。但是,我们可以声明一个友元类来访问和修改这些私有和受保护的成员。

    总结起来说,C++中的关键词提供了丰富的语言特性,使得我们可以编写出更安全、更易于理解和维护的代码。

  • 相关阅读:
    独热编码和Word2Vec的区别
    Python学习:整数类型(int)详解
    y140.第八章 Servless和Knative从入门到精通 -- Serving及实践(四)
    lvm + raid(逻辑磁盘+阵列)创建删除恢复 for linux
    鼠标行为HHT变换的工业互联网用户身份认证
    edge浏览器第三方插件网站
    MATLAB | 比生命游戏更自由的生命游戏
    有必要发这篇文章了!
    05 OpenCV图像混合技术
    【scikit-learn基础】--『监督学习』之 支持向量机分类
  • 原文地址:https://blog.csdn.net/weixin_50614301/article/details/133149932