首页 > 编程语言 >C++ 入门07:静态成员和常量成员

C++ 入门07:静态成员和常量成员

时间:2024-07-11 19:31:16浏览次数:12  
标签:常量 静态 string 成员 C++ 函数 变量 07

往期回顾:

C++ 入门04:数组与字符串-CSDN博客

C++ 入门05:类和对象-CSDN博客

C++ 入门06:类的进阶(构造函数的重载与拷贝构造函数)-CSDN博客


 一、前言

在前面文章的学习中,我们掌握了类和对象的基础知识以及构造函数的重载与拷贝构造函数。今天,我们将学习类的静态成员和常量成员。静态成员和常量成员是面向对象编程中重要的概念,了解它们有助于我们编写更高效和更安全的代码。

二、静态成员和常量成员

2.1、静态成员

静态成员,作为面向对象编程中的一个重要概念,是定义在类级别上而非实例级别上的。这意味着它们不依赖于类的任何特定对象实例,而是属于类本身。静态成员主要包括静态变量(或称为类变量)和静态函数(或称为类方法)。这些成员提供了一种机制,允许在类的所有实例之间共享数据和功能。

(1)静态成员变量

静态成员变量是那些被类的所有实例共享的变量。这意味着,无论创建了多少个类的实例,静态变量都只有一份拷贝。这些变量在内存中只有一个存储空间,由所有实例共同访问和修改(如果允许的话)。静态成员变量特别适用于存储那些与类本身相关,但与特定实例无关的数据。

A、特性
  1. 共享性:所有对象实例共享同一个静态成员变量的值。
  2. 初始化:静态成员变量在程序开始执行时(或在第一次被访问前,具体取决于编译器的实现)只初始化一次。
  3. 访问性:可以通过类名直接访问静态成员变量,也可以通过类的实例访问。
B、声明和定义

在C++或类似的语言中,静态成员变量的声明通常放在类的定义中,使用static关键字标识。然而,由于静态成员变量属于类而非类的任何特定对象,因此它们不能在类的定义中直接初始化(除非使用了常量表达式进行初始化,这种情况称为就地初始化)。相反,静态成员变量的定义(包括其初始化)必须在类的定义外部进行,并且只能进行一次。这通常是通过在类的实现文件中指定其类型和名称,并可能包含初始化表达式来完成的。

// 类的定义  
class MyClass {  
public:  
    static int staticVar; // 声明静态成员变量  
    // ... 其他成员 ...  
};  
  
// 静态成员变量的定义(包括初始化)  
int MyClass::staticVar = 0; // 在类外部定义并初始化静态成员变量

注意:如果静态成员变量是const整型或枚举类型,并且使用常量表达式进行初始化,那么它可以在类定义内部直接初始化,而无需在类外部进行定义。

静态成员变量的这种特性使得它们成为存储类级别数据(如计数器,用于跟踪已创建的实例数量)的理想选择。

示例:

#include <iostream>
using namespace std;

class Car {
public:
    string brand;
    string model;
    int year;
    static int carCount; // 声明静态成员变量

    Car(string b, string m, int y) {
        brand = b;
        model = m;
        year = y;
        carCount++; // 每创建一个对象,carCount 加 1
    }

    void displayInfo() {
        cout << "Brand: " << brand << endl;
        cout << "Model: " << model << endl;
        cout << "Year: " << year << endl;
    }
};

// 在类外部定义静态成员变量
int Car::carCount = 0;

int main() {
    Car car1("Toyota", "Corolla", 2020);
    Car car2("Honda", "Civic", 2019);

    cout << "Total cars: " << Car::carCount << endl; // 访问静态成员变量

    return 0;
}

在这个示例中,carCount 是一个静态成员变量,它在所有 Car 对象之间共享。每次创建一个 Car 对象,carCount 的值就会增加。

(2)静态成员函数

静态成员函数是定义在类级别上的一种特殊成员函数,它们与类本身相关联,而不是与类的某个特定对象实例相关联。这意味着,静态成员函数可以在没有创建类对象的情况下被调用,它们通过类名直接访问,而不是通过类的实例对象。

A、静态成员函数的特点
  1. 属于类而非对象:静态成员函数是类的组成部分,而不是任何特定对象的成员。因此,它们不依赖于类的实例变量,也不具有this指针(在C++中)。

  2. 访问限制:静态成员函数只能直接访问类的静态成员变量和静态成员函数。这是因为非静态成员变量和成员函数是特定于对象的,而静态成员函数在调用时并不绑定到任何特定的对象实例。

  3. 调用方式:静态成员函数可以通过类名直接调用,也可以通过类的实例对象调用(尽管这种调用方式在逻辑上并不常见,因为它违背了静态成员函数的初衷)。

B、静态成员函数与非静态成员的访问

由于静态成员函数不依赖于任何特定的对象实例,因此它们不能直接访问类的非静态成员变量和非静态成员函数。非静态成员是特定于对象的,它们的值或行为可能因对象的不同而有所差异。静态成员函数在调用时并不自动与任何对象实例相关联,因此没有途径来访问或修改非静态成员。

如果静态成员函数需要访问非静态成员,那么它必须显式地通过某个对象实例来调用这些成员。这通常是通过将对象实例作为参数传递给静态成员函数来实现的,但这会破坏静态成员函数的初衷,因为它将静态成员函数的调用与特定的对象实例绑定在一起。

语法:

class ClassName {
public:
    static 返回类型 静态成员函数名(参数列表);
};

示例:

#include <iostream>
using namespace std;

class Car {
public:
    string brand;
    string model;
    int year;
    static int carCount;

    Car(string b, string m, int y) {
        brand = b;
        model = m;
        year = y;
        carCount++;
    }

    static int getCarCount() { // 静态成员函数
        return carCount;
    }

    void displayInfo() {
        cout << "Brand: " << brand << endl;
        cout << "Model: " << model << endl;
        cout << "Year: " << year << endl;
    }
};

int Car::carCount = 0;

int main() {
    Car car1("Toyota", "Corolla", 2020);
    Car car2("Honda", "Civic", 2019);

    cout << "Total cars: " << Car::getCarCount() << endl; // 调用静态成员函数

    return 0;
}

在这个示例中,getCarCount 是一个静态成员函数,用于返回 carCount 的值。静态成员函数只能访问静态成员变量。

2.2、 常量成员

 常量成员是面向对象编程中一个重要的概念,用于确保类的某些成员在创建后保持不变,即它们的值或行为在对象的整个生命周期内都是恒定的。在类中,常量成员可以包括常量成员变量(也称为常量属性)和常量成员函数(也称为常量成员函数或只读成员函数)。这里,我们主要扩写常量成员变量的相关内容。

(1)常量成员变量

常量成员变量是通过在成员变量声明前加上const关键字来定义的。这个const修饰符表明该成员变量的值在对象被创建之后就不能被修改。常量成员变量提供了一种机制,用于在类的设计中嵌入那些不应该被改变的值,从而增加了代码的健壮性和可维护性。

A、特性:
  1. 初始化要求:常量成员变量必须在对象创建时被初始化。这可以通过在类的构造函数初始化列表中指定初始值来完成,而不能在类的声明中直接初始化(除非使用了C++11及以后版本中的就地初始化功能,但这通常不适用于常量成员变量,因为它要求使用常量表达式)。

  2. 不可变性:一旦常量成员变量被初始化,它的值就不能在对象的生命周期内被修改。这意呀着,任何尝试修改常量成员变量的操作都将导致编译错误。

  3. 访问控制:常量成员变量的访问控制(如publicprotectedprivate)与普通成员变量相同,但它们的不可变性是全局的,不受访问控制符的影响。

语法:

class ClassName {
public:
    const 数据类型 常量成员变量名;
    ClassName(参数列表) : 常量成员变量名(初始值) {}
};

示例:

#include <iostream>
using namespace std;

class Car {
public:
    const int maxSpeed; // 常量成员变量
    string brand;
    string model;
    int year;

    Car(string b, string m, int y, int ms) : maxSpeed(ms) {
        brand = b;
        model = m;
        year = y;
    }

    void displayInfo() {
        cout << "Brand: " << brand << endl;
        cout << "Model: " << model << endl;
        cout << "Year: " << year << endl;
        cout << "Max Speed: " << maxSpeed << " km/h" << endl;
    }
};

int main() {
    Car car1("Toyota", "Corolla", 2020, 180);
    car1.displayInfo();

    return 0;
}

在这个示例中,maxSpeed 是一个常量成员变量,它在构造函数中初始化,并且在对象的生命周期内不能修改。

(2)常量成员函数

常量成员函数在定义时加上 const 关键字,表示该函数不会修改对象的任何成员变量。

语法:

class ClassName {
public:
    返回类型 成员函数名(参数列表) const;
};

示例:

#include <iostream>
using namespace std;

class Car {
public:
    string brand;
    string model;
    int year;

    Car(string b, string m, int y) {
        brand = b;
        model = m;
        year = y;
    }

    void displayInfo() const { // 常量成员函数
        cout << "Brand: " << brand << endl;
        cout << "Model: " << model << endl;
        cout << "Year: " << year << endl;
    }
};

int main() {
    Car car1("Toyota", "Corolla", 2020);
    car1.displayInfo();

    return 0;
}

 在这个示例中,displayInfo 是一个常量成员函数,表示该函数不会修改 Car 对象的任何成员变量。


以上就是 C++ 程序的静态成员和常量成员的基础知识点了。静态成员属于类而不是对象,常量成员在对象的生命周期内不能修改。

都看到这里了,点个赞再走呗朋友~

加油吧,预祝大家变得更强!

标签:常量,静态,string,成员,C++,函数,变量,07
From: https://blog.csdn.net/LF__plus/article/details/140358775

相关文章

  • python 冷知识 66 个 0708
    66个有趣的Python冷知识内联注释可以在代码行尾使用#进行内联注释,例如x=10#这是一个内联注释。多行注释多行注释可以用三个引号'''或"""包裹。分数fractions模块提供了分数类型,可以精确表示分数值。小数decimal模块提供了小数类型,可以进行精确的浮......
  • C++算法实践07-回文数
    一、题目:给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。示例1:输入:x=121输出:true示例 2:输入:x=-121输出:false解释:从左向右读,为-121。从右......
  • C++算法实践06-整数反转
    一、题目:给你一个32位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。如果反转后整数超过32位的有符号整数的范围 [−231, 231 −1] ,就返回0。假设环境不允许存储64位整数(有符号或无符号)。示例1:输入:x=123输出:321示例2:输入:x=-123输出:-321示例......
  • 2024-07-11 npm publish报错合集
    报错1:ThispackagehasbeenmarkedasprivatenpmERR!你的包被设为私有模式了。npmERR!codeEPRIVATEnpmERR!ThispackagehasbeenmarkedasprivatenpmERR!Removethe'private'fieldfromthepackage.jsontopublishit.原因:你发布的包被标记为私有了,如果......
  • 代码随想录算法训练营第四天 | Python | LeetCode24.两两交换链表中的节点、19.删除链
    LeetCode24.两两交换链表中的节点题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/description/文章/视频链接:https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html#%E7%AE%9......
  • C++冒泡排序(使用vector动态数组)
    #include<iostream>#include<vector>usingnamespacestd;voidsort(vector<int>&a){  constintsize=a.size();  inttemp;  intflag=1;  while(flag==1)  {  flag=0;  for(inti=0;i<size;++i)  {   if(a[i]>......
  • c++方法
    std::transform方法std::transform是C++标准库算法中的一个非常有用的函数,它定义在头文件中。这个函数用于将给定范围内的每个元素按照指定的操作进行转换,并将转换结果存储在另一个位置(可以是原始范围的另一个容器,或者完全不同的位置)。std::transform提供了一个灵活的......
  • N皇后问题(C++)
    问题描述N皇后问题是一个经典的计算机科学问题,要求在一个N×N的棋盘上放置N个皇后,使得彼此不互相攻击。攻击的定义包括皇后在同一行、同一列或同一对角线上。规则任意两个皇后不能在同一行。任意两个皇后不能在同一列。任意两个皇后不能在同一条斜线上(包括主对角线和副对角......
  • PTA 7-2 数组循环左移--C++
    本题思路:本题可以用数组或者指针来解决问题,本题我们如果我们用数组来解决问题的话,数组循环左移,就相当后面的数组右移过来,如i位置的就相当于i+m的位置的数组,大概这样的思路,就没有问题了#include<iostream>usingnamespacestd;intmain(){intn,m;cin>>n>>m;......
  • C++ 中的 lowbit
    lowbit的定义首先了解lowbit的定义\(lowbit(n)\),为\(n\)的二进制原码中最低的一位\(1\)以及其后面的\(0\)所表示的数举个简单的例子:将\(10\)使用二进制表示为\(1010\)其中最低位的\(1\)为第2位(\(_{10}1_0\),从右往左数)此时\(lowbit(10)\)使用二进制表示为......