static关键字与类的静态成员

学在前面

static关键字在C和C++编程中具有多种用途,根据上下文可改变其行为。下面从五个方面详细解释static关键字在这两种语言中的使用。

static 关键字

1、概念

在C和C++中,static关键字用于声明变量或函数具有静态存储期。即这些变量或函数在程序的整个运行期间都存在,而不是作用域结束时被销毁。

2 为什么使用 static

使用static关键字的主要原因包括:

延长变量生命周期:在函数内部声明的static变量,其生命周期会延伸到整个程序运行期间,而不仅仅是该函数被调用时。

限制变量作用域:在文件级(全局)作用域中使用static关键字可以限制变量或函数的作用域,使其仅在声明它的文件内部可见。

控制链接:控制变量或函数的链接属性,使其具有内部链接,即只能在定义它的文件内访问。

实现类成员变量的共享:在C++中,static成员变量被类的所有对象共享,而不是每个对象都有自己的副本。

3 如何使用 static

3.1 修饰局部静态变量

在程序的整个运行期间只被初始化一次。

函数调用之间保持其值。

void func()

{

static int count = 0; // 只在第一次调用func时初始化,之后每次调用都会保留上一次的值

count++;

}

3.2 修饰全局静态变量

变量的作用域被限制在定义它们的文件内,其它文件不可见。

static int g_var = 10; // 仅在定义它的文件内可见

3.3 修饰函数

函数的作用域被限制在定义它们的文件内,其它文件不可见。

static void helperFunction(); // 仅在定义它的文件内可被调用

4、何时使用static

局部静态变量:当你需要一个在函数调用之间保持其值的变量时。

全局静态变量:当你需要一个仅在某个文件内使用的全局变量时。

静态函数:当你希望一个函数只在定义它的文件内可见时。

C++中的静态成员变量:当你需要一个类的所有对象共享的数据时。

C++中的静态成员函数:当你需要一个可以访问静态成员变量,但不依赖于特定对象实例的函数时。

5、优缺点

|---------|----------------------------|---------------------------------------------|
| 修饰对象 | 优点 | 缺点 |
| 局部变量 | 可以在函数调用之间保持状态。 | 可能导致资源泄漏或不必要的内存占用(如果变量占用了大量内存或资源)。 |
| 局部变量 | 避免了重复初始化。 | 使得代码更加难以理解和调试,因为状态保持可能引入隐藏的错误。 |
| 函数或全局变量 | 提供了封装和模块化,避免命名冲突。 | 限制了代码的可重用性和灵活性。 |
| 函数或全局变量 | 允许在不同的文件中定义同名变量或函数而不会互相干扰。 | 需要在多个文件中共享数据时,需要额外的机制(如通过接口函数或全局变量加extern)。 |
| 类的数据 成员 | 允许所有对象共享同一个值。 | 访问静态成员变量需要通过类名或对象(尽管类名访问更常见),这可能使代码更加复杂。 |
| 类的数据 成员 | 可以用于实现类级别的计数器、缓存等。 | 需要特别注意多线程环境下的同步问题。 |
| 类的函数 成员 | 可以用来实现与类相关的功能,但不需要访问对象的状态。 | 不能访问非静态成员变量或调用非静态成员函数,限制了其功能。 |
| 类的函数 成员 | 可以用于实现工厂方法、帮助函数等。 | 可能导致设计上的混淆,特别是如果静态成员函数和非静态成员函数具有相似名称时。 |

1、类的静态成员变量

类的静态成员变量可以是常量、引用、指针、类类型等类型,其属于类本身,不与任何类实例绑定。经常被用作类级别的默认值或计数器。

1.1 声明与定义静态成员变量

必须在类内声明,在类外定义,且只能被定义一次,定义时不加static关键字;其初始化不由构造函数完成。

class MyClass {

public:

static int sharedVar_; // 声明静态成员变量,在变量类型前加static关键字

};

int MyClass::sharedVar_ = 0; // 定义静态成员变量,并进行初始化

1.2 如何使用静态成员变量

(1)通过类名访问

int value = MyClass::staticVar_;

(2)通过对象访问(不推荐,但语法上允许)

MyClass obj;

obj.staticVar_ = 5;

int value = obj.staticVar_;

(3)静态成员变量作为默认实参

class MyClass {

public:

constexpr static int DEFAULT_VALUE = 42;

void someMethod(int value = DEFAULT_VALUE) { }

};

1.3 静态成员变量的特征

共享性:所有对象共享同一个静态成员变量。即修改一个对象的静态成员变量会影响所有其它类实例(方便与风险并存)。

类作用域:静态成员变量在类作用域中定义,可以通过类名直接访问,也可以通过对象访问(但不推荐)。

初始化:静态成员变量必须在类外部进行初始化,而不能在类定义中直接初始化;C++11及更高版本允许在类内部初始化常量静态成员变量(但某些编译器可能仍然要求在类外部进行定义)。

生命周期:静态成员变量的生命周期贯穿整个程序运行期间,从程序开始到程序结束。

2、类的静态成员函数

2.1 声明静态成员函数

class MyClass {

public:

static void staticFunction()

{

// 可以直接访问静态成员变量,但不能直接访问非静态成员变量

sharedVar_++;

}

};

2.2 定义静态成员函数

静态成员函数在类内部或外部定义均可。若在类内部定义(即内联定义),则直接编写函数体即可;若在类外部定义,则需要使用"类名::"指定函数属于哪个类,不需要static关键字。

class MyClass {

public:

static void staticFunction()

{

std::cout << "This is a static function." << std::endl; //类内定义

}

};

void MyClass::staticFunction()

{

std::cout << "This is a static function (defined outside the class)." << std::endl; //类外定义

}

2.3 静态成员函数的特征

1、属于类本身

属于类本身,不是类的任何特定对象。因此,它们不能访问类的非静态成员变量。

2、无 this 指针

由于静态成员函数不属于任何对象,因此它们没有this指针。这意味着它们不能访问对象的成员变量(非静态的)或成员函数(非静态的,除非它们是 const 静态成员函数并且只访问 const 成员)。

3、直接通过类名调用

静态成员函数可以直接通过类名调用,而不需要创建类的对象。

4、只能访问静态成员

静态成员函数只能直接访问类的静态成员变量和其它静态成员函数。

5、不能声明为 virtual

静态成员函数不能是虚函数,因为虚函数机制依赖于对象的 this 指针,而静态成员函数没有this指针。

相关推荐
Fairy_sevenseven几秒前
【三十一】【QT开发应用】QPushButton与QMenu
开发语言·qt·命令模式
-芒果酱-11 分钟前
DDA画线算法例题
开发语言·c++·算法
小飞猪Jay11 分钟前
C++面试速通宝典——20
c++·面试
chian-ocean12 分钟前
【C++11】新特性
java·开发语言·c++
猪蹄手14 分钟前
C/C++复习(一)
c语言·开发语言·c++
s_little_monster14 分钟前
【QT】信号和槽
开发语言·数据库·c++·经验分享·笔记·qt·学习
多喝热水-多读书15 分钟前
Qt C++设计模式->中介者模式
c++·qt·设计模式·中介者模式
产幻少年17 分钟前
golang语法
开发语言·golang
小哈里18 分钟前
【虚拟化】内核级虚拟化技术KVM介绍,全/半虚拟化的区别,使用libvirt搭建虚拟化平台(go/java/c++)
java·c++·golang·虚拟化·kvm
长天一色27 分钟前
【python 简易入门应用教程】第一部分:Python 基础
开发语言·python