《C++避坑神器·四》静态成员变量和静态成员函数

简介: 《C++避坑神器·四》静态成员变量和静态成员函数


概要

静态成员变量和静态成员函数一些注意点

技术细节

静态成员变量

(1)所有对象共享一份数据,一处修改处处改变

(2)编译阶段就分配内存,全局区

(3)类内声明,类外初始化操作(注意:初始化一定放在.cpp里面不然会报重定义错误

class Person
{
public:
  static int age; 
}
int Person::age = 20;

不给值的初始化做法:

类中:static mutex m_mutex;

类外:mutex Person::m_mutex;

静态成员变量不属于某个对象(只有非静态的成员变量才属于类的对象上),所有对象都可以共享一份数据,因此静态成员变量有两种访问方式:

(1)通过对象进行访问

Person p;

cout << p.age << endl;

(2)通过类名访问

cout << Person::age << endl;

注意:如果静态成员变量定义为私有,类外不可以直接访问

静态成员函数

(1)所有对象共享同一个函数

(2)静态成员函数只能访问静态成员变量(非静态可以访问静态,静态不能访问非静态)

如果想访问非静态成员变量需要在内部创建对象或者对象指针调用非静态变量

静态成员函数不属于类的对象上,访问方式:

(1)通过对象访问

Person p;

p.func();

(2)通过类名访问

Person::func();

注意:静态成员函数也有访问权限,被定义在私有下类外不可以直接访问

注意点:

1、父类的static变量和函数在派生类中依然可用(可以继承),但是受访问性控制(比如,父类的private域中的就不可访问),而且对static变量来说,派生类和父类中的static变量是共用空间的(一处修改处处改变),这点在利用static变量进行引用计数的时候要特别注意。

2、static函数没有“虚函数”一说。因为static函数实际上是“加上了访问控制的全局函数”,全局函数哪来的什么虚函数。

3、通常,空对象占用1个字节的内存空间,是为了区分空对象在内存中占用的位置,每个空对象都有一个独一无二的内存地址

class Person
{
}
int main()
{
  Person p;
  std::cout << sizeof(p) << std::endl; //1个字节
  return 0;
}

需要注意的是一旦类里面有东西,只按类中的变量大小给对象分配内存,静态成员变量、静态成员函数、非静态成员函数不属于类的对象上,所以给对象分配内存时会忽略他们内存大小。

class Person
{
public:
  int age;           //非静态成员变量属于类的对象
  char arr[7];
  static int height; //静态成员变量不属于类的对象
}
int main()
{
  Person p;
  std::cout << sizeof(p) << std::endl; //4+7+1 = 12个字节,要字节对齐
  return 0;
}

小结

只有非静态成员变量属于类的对象上,其他的(非静态成员函数、静态成员变量、静态成员函数都不属于类的对象上因此计算对象的内存大小时都会忽略,并且静态的可以直接类名访问),非静态成员变量和非静态成员函数是分开存储的,由于非静态成员函数不属于类的对象上所以只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码。

相关文章
|
3月前
|
存储 C++
C++语言中指针变量int和取值操作ptr详细说明。
总结起来,在 C++ 中正确理解和运用 int 类型地址及其相关取值、设定等操纵至关重要且基础性强:定义 int 类型 pointer 需加星号;初始化 pointer 需配合 & 取址;读写 pointer 执向之处需配合 * 解引用操纵进行。
353 12
|
5月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
147 0
|
8月前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
452 6
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
485 6
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
274 0
C++ 多线程之线程管理函数
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
203 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
C语言 C++
实现两个变量值的互换[C语言和C++的区别]
实现两个变量值的互换[C语言和C++的区别]
172 0
|
9月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
5月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
227 0