C++ | 静态成员变量与静态成员函数(static关键字、this指针)

举报
mindtechnist 发表于 2023/05/11 13:59:59 2023/05/11
【摘要】 C++之静态成员变量与静态成员函数(static关键字、this指针)。



基本语法

  • 静态成员提供了一个同类对象的共享机制,静态成员变量属于整个类,该类所定义的对象共享同一个静态成员变量(无论定义多少个对象,他们的static成员变量都是同一个)。
  • 静态成员变量必须在外部声明并初始化。
  • 静态成员函数中不能使用非静态成员变量,因为静态成员函数提供不依赖于类数据结构的共同操作,它没有this指针。静态成员是属于整个类的,他不依赖于某个对象,而普通成员函数专属于类定义的个某个对象,这时候如果调用该静态成员函数,编译器不知道该函数中被引用的普通成员变量属于哪个具体对象,故报错(具体将在下面代码中详细分析)。

代码分析

代码如下:

#include <iostream>
using namespace std;
class MyClassA
{
public:
    MyClassA()
    {
        a = 10;
        cout << "无参构造函数调用" << endl;
    }
    void PrintA()
    {
        cout << "静态成员 a = " << a << endl;
    }
public:
    static int a;
};
int MyClassA::a = 0; //必须在外部定义!!!否则报错
                     //错误   LNK2001 无法解析的外部符号 "public: static int MyClassA::a" 
//静态成员变量测试
void FuncTest1()
{
    MyClassA A1, A2;
    A1.PrintA();
    //静态成员变量的第一种访问方式
    A2.a++;
    A1.PrintA();
    //静态成员变量的第二种访问方式
    MyClassA::a++;
    A1.PrintA();
    A2.PrintA();
}
class MyClassB
{
public:
    static void PrintStaticValue()
    {
        cout << "静态成员函数中的静态变量   " << "b2 = " << b2 << endl;
    }
    static void PrintValue()
    {
        //cout << "静态成员函数中的非静态变量   " << "b1 = " << b1 << endl;
        //错误(活动)    E0245   非静态成员引用必须与特定对象相对
        //错误    C2597   对非静态成员“MyClassB::b1”的非法引用   
    }
    /*
    静态成员函数中只能使用静态变量,不能使用非静态成员变量,因为非静态成员变量是属于某个对象的,
    当我们  MyClassB::PrintValue() 的时候,编译器不知道该使用哪个对象(B1还是B2还是B3...)的非
    成员变量b1
    */
private:
    int b1;
    static int b2;
};
int MyClassB::b2 = 0;
//静态成员函数测试
void FuncTest2()
{
    MyClassB B;
    //静态成员函数的第一种调用方式
    B.PrintStaticValue();
    //静态成员函数的第二种调用方式
    MyClassB::PrintStaticValue();
    MyClassB B1, B2, B3;
    //MyClassB::PrintValue();
    //我应该使用哪个b1???是打印B1的b1,还是打印B2的b1,又或者是B3的b1?
    //故报错
}
int main()
{
    FuncTest1();
    FuncTest2();
    system("pause");
    return 0;
}

成员变量与成员函数的存储与this指针

C++类对象中的成员变量和成员函数是分开存储的

  • 成员变量:
    ①普通成员变量:存储于对象中,与struct变量有相同的内存布局和字节 对齐方式。
    ②静态成员变量:存储于全局数据区中。
  • 成员函数:存储于代码段中。

既然类的成员函数存储在代码区,也就是说所有的对象共用一块代码,那么当具体对象调用成员函数的时候,怎么区分成员函数中使用的变量是哪个对象的呢?比如:

class MyClass
{
public:
    void PrintValue()
    {
        a = 10;
        cout << a << endl;
    }
public:
    int a;
};
int main()
{
    MyClass A1, A2, A3;
    A1.PrintValue();
    
    system("pause");
    return 0;
}

在上段代码中,PrintValue函数中用的变量a是A1的还是A2的还是A3的呢?

C++编译器会对成员函数进行内部处理,加一个this指针,this指针指向调用该成员函数的对象,这样就知道是哪个对象调用了该成员函数,并使用该对象的成员变量值。代码如下:

void PrintValue(MyClass* this)
{
    this->a = 10;
    cout << this->a << endl;
}

在调用的时候

A1.PrintValue();

会被转化为

PrintValue(&A1);

由此可见,这也是使用了C语言的指针实现的。实际上,面向对象也是在面向过程的基础上实现的,只不过是在此基础上加了一层封装,对用户进行了隐藏而已。

对于静态成员函数,不会做这种转化,因为静态成员函数是属于整个类的,这也正是为什么静态成员函数中不能使用非静态成员变量,因为静态成员函数中没有this指针,编译器不知道使用的成员变量是哪个对象的变量。

普通成员函数都包含指向具体对象的this指针,哪个对象调用成员函数,this指针就指向这个对象。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。