C++从入门到精通——static成员


前言


一、static成员

概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。

静态成员是指属于类而不属于类的任何对象的成员。静态成员在类的所有对象之间共享,并且可以在不创建对象的情况下被访问。静态成员包括静态变量和静态方法。

静态变量是类的所有对象之间共享的变量。它们在内存中只有一份拷贝,并且可以直接通过类名访问。静态变量在类的任何对象被创建之前就被初始化,它们的值在所有对象之间是一致的。

静态方法是属于类而不属于任何对象的方法。它们可以直接通过类名调用,而不需要创建类的对象。静态方法通常用于执行与类相关的操作,而不涉及特定对象的状态。

静态成员在类的定义中使用static关键字进行声明。例如,以下是一个使用静态变量和静态方法的示例:

class MyClass {
public:
    static int staticVar; // 静态变量声明
    static void staticMethod(); // 静态方法声明
};

int MyClass::staticVar = 0; // 静态变量定义和初始化

void MyClass::staticMethod() {
    // 静态方法的实现
    cout << "This is a static method." << endl;
}

int main() {
    MyClass::staticVar = 10; // 静态变量的访问
    MyClass::staticMethod(); // 静态方法的调用
    return 0;
}

在上述示例中,静态变量staticVar和静态方法staticMethod属于类MyClass,可以直接通过类名进行访问和调用。

例题

实现一个类,计算程序中创建出了多少个类对象。

class A
{
public:
	A() { ++_scount; }
	A(const A& t) { ++_scount; }
	~A() { --_scount; }
	static int GetACount() { return _scount; }
private:
	static int _scount;
};

int A::_scount = 0;

void TestA()
{
	cout << A::GetACount() << endl;
	A a1, a2;
	A a3(a1);
	cout << A::GetACount() << endl;
}

以上代码定义了一个名为A的类,该类包含一个私有的静态成员变量_scount,一个默认构造函数,一个拷贝构造函数和一个析构函数。在main函数中,调用TestA函数。

TestA函数中,首先调用A::GetACount()函数获取当前A类的对象数量,然后创建了两个A类的对象a1a2,并将a1传递给a3的拷贝构造函数。再次调用A::GetACount()函数获取当前A类的对象数量。

_scount是一个静态成员变量,它在类定义外进行初始化,并在类定义中被声明为私有。该变量用于记录A类的对象数量。默认构造函数和拷贝构造函数都会在对象创建时将_scount自增1,析构函数会在对象销毁时将_scount自减1。

因此,输出结果将显示A类对象的数量。首先是0,因为还没有创建任何A类的对象。然后是3,因为在TestA函数中创建了两个对象(a1a2),并进行了一次拷贝构造(a3)。最后,在TestA函数结束后,对象被销毁,_scount减少到0。

二、 static成员的特性

特性

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受publicprotectedprivate 访问限定符的限制

例题

静态成员函数可以调用非静态成员函数吗

静态成员函数可以调用非静态成员函数,但需要通过对象或者指针来调用。因为非静态成员函数是依赖于具体的对象或者实例的,而静态成员函数是独立于对象或者实例的,所以在静态成员函数中不能直接访问非静态成员变量和非静态成员函数。但可以通过将对象作为参数传递进来或者通过对象指针来调用非静态成员函数。

非静态成员函数可以调用类的静态成员函数吗

非静态成员函数可以调用类的静态成员函数。在非静态成员函数中,可以使用类名和作用域解析操作符(::)来调用静态成员函数。

三、static成员的注意事项

static不能给缺省值

在这里插入图片描述
在C++中,static关键字用于声明静态成员变量或静态函数。在声明静态成员变量时,不能直接为其设置缺省值。

其中一个原因是缺省值是要走初始化列表的,而static是不会走初始化列表。

除此之外,因为静态成员变量在编译阶段就已经被分配了内存空间(即在静态区),并没有被放置在对象的内存空间中。静态成员变量是属于整个类而不是某个具体对象的,它的生命周期独立于任何对象的创建和销毁。

如果允许为静态成员变量设置缺省值,那么在编译阶段就需要为所有的静态成员变量分配空间并为其赋值。这将引入额外的开销和复杂性,因为静态成员变量的初始值可能会依赖于其他静态成员变量或静态函数的结果。

为了避免这种复杂性和性能开销,C++规定了静态成员变量不能直接设置缺省值。可以在类外部定义静态成员变量,并在类外部进行初始化赋值:

class MyClass {
    static int myStaticVariable;
};

int MyClass::myStaticVariable = 0; // 在类外部进行初始化赋值

需要注意的是,如果不在类外部进行初始化赋值,静态成员变量的初始值将是未定义的。因此,为了保证静态成员变量的可靠性,最好在类外部进行初始化赋值。

static修饰变量和修饰函数的区别

C++中,static关键字可以用于修饰变量和函数,并且在两者之间有一些区别。

静态变量(static variable):

  • 静态变量被存储在静态存储区,其生命周期延长至整个程序的运行期间。
  • 静态变量只在声明它的作用域内可见,不能被其他文件访问。
  • 静态变量的初始化只会在程序第一次进入声明它的作用域时执行一次,并且只能在声明时给定初值。
  • 静态变量的作用域限制在声明它的函数或类中,但它的值在函数调用之间保持保持不变。

静态函数(static function):

  • 静态函数属于类而不是对象,它可以直接通过类名调用,无需创建对象实例。
  • 静态函数没有this指针,因此无法访问非静态成员变量或成员函数。
  • 静态函数只能直接访问静态成员变量或调用其他静态函数。

示例

当我们在C++中定义了一个静态函数后,可以通过以下方式进行调用:

#include <iostream>

class MyClass {
public:
    static void staticFunction() {
        std::cout << "This is a static function." << std::endl;
    }
};

int main() {
    // 通过类名直接调用静态函数
    MyClass::staticFunction();

    return 0;
}

在上面的例子中,我们定义了一个名为MyClass的类,并在该类中声明了一个静态函数staticFunction。在main函数中,我们通过类名MyClass::staticFunction()的方式直接进行调用。

输出结果将会是"This is a static function."

需要注意的是,因为静态函数不依赖于对象实例,所以可以通过类名直接访问。而不需要先创建对象实例。

总结

  • 静态变量的生命周期长,作用域限制在声明它的作用域内,值在函数调用之间保持不变。
  • 静态函数属于类而不是对象,无需创建对象实例,只能访问静态成员变量和调用其他静态函数。

四、练习题

提示:使用本文所提到的静态函数和静态变量来解决

JZ64 求1+2+3+…+n


相关推荐

  1. C++入门精通——nullptr

    2024-04-22 05:14:01       23 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-22 05:14:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-22 05:14:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-22 05:14:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-22 05:14:01       20 阅读

热门阅读

  1. VMware虚拟机ens33没有IP的解决办法

    2024-04-22 05:14:01       14 阅读
  2. c语言如何创建一个链表

    2024-04-22 05:14:01       14 阅读
  3. CTF 听说是rc4算法

    2024-04-22 05:14:01       11 阅读
  4. SQL约束

    SQL约束

    2024-04-22 05:14:01      12 阅读
  5. Oracle imp导入数据后中文乱码

    2024-04-22 05:14:01       14 阅读
  6. docker配置minio、redis、nacos

    2024-04-22 05:14:01       11 阅读
  7. Stable Diffusion,controlnet扩展

    2024-04-22 05:14:01       14 阅读
  8. C++ 随机数

    2024-04-22 05:14:01       11 阅读