C++类中静态变量和静态方法使用介绍

C++类中静态变量和静态方法使用介绍刷剑指offer第64题涉及到类内静态成员与方法的知识,有点模糊,找了两篇博客整理一下。转自:https://www.cnblogs.com/sixue/p/3997324.html    最近一直看c++相关的项目,但总是会被c++类中的静态成员变量与静态成员函数的理解感觉很是模糊,不明白为什么类中要是用静态成员变量.于是在网上搜集了一些资料,自己再稍微总结下。静态成员的概…

大家好,又见面了,我是你们的朋友全栈君。

刷剑指offer第64题涉及到类内静态成员与方法的知识,有点模糊,找了两篇博客整理一下。

C++类中静态变量和静态方法使用介绍

转自:https://www.cnblogs.com/sixue/p/3997324.html

       最近一直看c++相关的项目,但总是会被c++类中的静态成员变量与静态成员函数的理解感觉很是模糊,不明白为什么类中要是用静态成员变量.于是在网上搜集了一些资料,自己再稍微总结下。

静态成员的概念:

       静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员先于类的声明而存在于内存,也可以根据类声明的对象来访问.而非静态成员必须实例化之后才会分配内存.

非静态成员的概念:

      所有没有加static的成员都是非静态成员.而类被实例化后,可以通过实例化的类名进行访问.非静态成员的生存期决定于该类的生存期.而静态成员不存在生产期的问题,因为它始终驻留在内存.

 

分两个方面来总结,面向过程与面向对象.

一:面向过程中的static关键字

1.静态全局变量

定义全局变量前,加上关键字static,该变量就被定义成了一个静态全局变量.

特点:

  • 该变量在全局数据区分配内存.
  • 初始化:如果不是显示初始化,那么将被隐式初始化为0.
  • 访变量只在本文件可见,即应该为定义之处开始到本文件结束.

程序在内存中一般分为四个区域:

  • 代码区
  • 全局数据区
  • 堆区
  • 栈区

一般程序由new产生的动态数据放在堆区,函数内部的自动变量放在栈区.自动变量一般会随着函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量)都存放在全局数据区.因此它们并不会随着函数的退出而释放空间.

 static int n;//定义静态全局变量

改为:  int n;//定义全局变量

区别:

  静态全局变量不能被其他文件所用.因而其他文件可以定义相同名字的变量,而不会发生冲突.

例子:

//Example
//File 1
#include <iostream>
void fn();

static int n;//定义静态全局变量(只能在本文件中使用)
void main(){
   n=20;
   cout<<n<<endl;
   fn();
}


//File 2
#include <iostream>
extern int n;(可在别的文件中引用这个变量)
void fn(){
    n++;
    cout<<n<<endl;
}//编译并运行Example,就会发现上述代码分别通过编译,但Link时会出错.

如果将static int n改为 :int n;
再次编译运行程序,就不会出错.

2.静态局部变量

 在局部变量前加上static 关键字,就定义了静态局部变量.

特点:

  •   该变量在全局数据区分配内存.
  •   初始化时:如果不是显示初始化,那么将隐式初始化为0.
  •   它始终驻留在全局数据区,直到程序结束.但其作用域为局部作用域.当定义它的函数或语句块时,其作用域随之结束.

3.静态函数:在函数的返回类型前加上static关键字.

特点:

静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其他文件可用.

 

二:面向对象的static关键字

1.静态数据成员

在类中数据成员的声明前加上static,该成员是类的静态数据成员.

例子:

//example 2
#include <iostream>

class MyClass{
public:
     MyClass(int a,int b,int c);
     void GetSum();

private:
    int a,b,c;
    static int sum;//声明静态数据成员
};

int MyClass::sum=0;//定义并初始化静态数据成员

 

 

特点:

对于非静态数据成员,每个类对象都有自己的拷贝.而静态数据成员被当做是类的成员,无论这个类被定义了多少个,静态数据成员都只有一份拷贝,为该类型的所有对象所共享(包括其派生类).所以,静态数据成员的值对每个对象都是一样的,它的值可以更新.

因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以它不属于特定的类对象,在没有产生类对象前就可以使用.

 

2.静态成员函数

      与普通的成员函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针.从这个意义上来说,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,只能调用其他的静态成员函数.

 

转自:https://www.cnblogs.com/ppgeneve/p/5091794.html

静态成员的提出是为了解决数据共享的问题。实现共享有许多方法,如:设置全局性的变量或对象是一种方法。但是,全局变量或对象是有局限性的。这一章里,我们主要讲述类的静态成员来实现数据的共享。

静态数据成员

  在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。

  使用静态数据成员可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。

静态数据成员的使用方法和注意事项如下:

  1、静态数据成员在定义或说明时前面加关键字static。//静态变量的定义

  2、静态成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式如下:

    <数据类型><类名>::<静态数据成员名>=<值>  //静态变量的初始化

这表明:

       (1) 初始化在类体外进行,而前面不加static,(这点需要注意)以免与一般静态变量或对象相混淆。

  (2) 初始化时不加该成员的访问权限控制符private,public等。

  (3) 初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员。

  3、静态数据成员是静态存储的,它是静态生存期,必须对它进行初始化。

  4、引用静态数据成员时,采用如下格式:

   <类名>::<静态成员名>   //静态变量的使用方式

  如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员。

下面举一例子,说明静态数据成员的应用:

​
class StaticTest
{
public:
    StaticTest(int a, int b, int c);
    void GetNumber();
    void GetSum();
    static void f1(StaticTest &s);
private:
    int A, B, C;
    static int Sum;
};



#include "StaticTest.h"
#include <iostream>
using namespace std;

int StaticTest::Sum = 0;//静态成员在此初始化

StaticTest::StaticTest(int a, int b, int c)
{
    A = a;
    B = b;
    C = c;
    Sum += A + B + C;
}

void StaticTest::GetNumber()
{
    cout << "Number = " << endl;
}

void StaticTest::GetSum()
{
    cout << "Sum = " << Sum <<endl;
}

void StaticTest::f1(StaticTest &s)
{
    
    cout << s.A << endl;//静态方法不能直接调用一般成员,可以通过对象引用实现调用
    cout << Sum <<endl;
}

#include "StaticTest.h"
#include <stdlib.h>


int main(void)
{
    StaticTest M(3, 7, 10), N(14, 9, 11);
    M.GetNumber();
    N.GetSum();
    M.GetNumber();
    N.GetSum();
    StaticTest::f1(M);
    system("pause");
    return 0;
}

​

注意,static成员的初始化要在实现中进行,不能在头文件进行。

从输出结果可以看到Sum的值对M对象和对N对象都是相等的。这是因为在初始化M对象时,将M对象的三个int型数据成员的值求和后赋给了Sum,于是Sum保存了该值。在初始化N对象时,对将N对象的三个int型数据成员的值求和后又加到Sum已有的值上,于是Sum将保存另后的值。所以,不论是通过对象M还是通过对象N来引用的值都是一样的,即为54,s.A=3。

静态成员函数

  静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。

  在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员(这点非常重要)。如果静态成员函数中要引用非静态成员时,可通过对象来引用。从中可看出,调用静态成员函数使用如下格式:<类名>::<静态成员函数名>(<参数表>);

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140544.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • javascript和java哪个快_Javascript与Java相比有多快?

    javascript和java哪个快_Javascript与Java相比有多快?Java 和 JavaScript 都是编程语言 编程语言只是一堆抽象的数学规则 编程语言不快 或慢 他们只是 应用程序的性能与语言无关 最重要的因素是应用程序架构 然后是算法效率 然后微优化 然后是编译器 解释器的质量 然后是 CPU 也许两个之间的其他几个步骤 然而 语言不直接起作用 当然 如果你在谈论基准测试 那么特定的基准测试也会发挥作用 基准测试的执行情况 运行得如何好 执行基准测试的人是否

    2025年10月19日
    2
  • sql2008备份集中的数据库备份与现有的xxx数据库不同解决方法「建议收藏」

    sql2008备份集中的数据库备份与现有的xxx数据库不同解决方法「建议收藏」今天部署一个asp老项目,在用MSSQL数据库备份文件还原数据库时,发生了问题。提示:sql2008备份集中的数据库备份与现有的xxx数据库不同。百度找到了这篇文章:sql2008备份集中的数据库备份与现有的xxx数据库不同解决方法但我和他重现问题的步骤不一样,他是以文件和文件组的方式还原出现了问题,而我是以数据库的方式还原出现了问题。换句话说,他的解决方案里的步骤就是我出错的步骤,如图:…

    2022年5月13日
    48
  • ajax使用案例

    ajax使用案例1、初步了解这里可以修改网络快和慢。限网,流量式的,做模拟的。network->all代表加载的所有事件后面的那个显示有/,这个是首路由。后面有很多svg和js等文件想要这个服务器的地址

    2022年7月2日
    23
  • 如何优雅地送妹子礼物给她_怎样送女生礼物让女生接受

    如何优雅地送妹子礼物给她_怎样送女生礼物让女生接受一颗林萌 ,剁手已剁成哆啦A梦。刘巍然-学酥 等 15240 人赞同—————————————————————————————–有转载需要请私信,不接受未通知作者本人直接转载的行为,按原创法规直接举报。因为工作原因经常接触买买买,加上生活里经常剁手.

    2022年10月4日
    2
  • 6种php加密解密方法

    6种php加密解密方法<?phpfunctionencryptDecrypt($key,$string,$decrypt){if($decrypt){$decrypted=rtrim(mcrypt_d

    2022年8月1日
    12
  • 运维面试题整理

    运维面试题整理文章目录原题前言1.Nginx反向代理配置,此类urlwww.abc.com/refuse,禁止访问,返回4032.如何使用iptables将本地80端口的请求转发到8080端口,当前主机IP为192.168.16.1,其中本地网卡eth0:3.如何查看Linux系统当前的状态,cpu内存的使用情况及负载4.nginx如何重定义或者添加发往后端服务器的请求头5.编写shell脚本,将当前目录下大于10K的文件转移到/tmp目录下6.写出你所了解的门户网站的服务架构,可用什么方式实现的高可用、负

    2022年6月11日
    28

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号