【C++面向对象编程】(二)this指针和静态成员

文章目录

  • this指针和静态成员
    • this指针
    • 静态成员

this指针和静态成员

this指针

C++中类的成员变量和成员函数的存储方式有所不同:

  • 成员变量:对象的成员变量直接作为对象的一部分存储在内存中。
  • 成员函数:成员函数(非静态成员函数)不直接存储在对象的内存中。它们的代码(即函数体中的指令)存储在代码区中。

当我们创建一个类的多个对象时,这些对象的成员函数的代码是共享的,也就是说,无论我们创建多少个类的对象,这些函数的代码都只有一份。 但是,每个对象都有自己独立的成员变量。为了在这些共享的成员函数内部引用和修改特定对象的成员变量,C++提供了this指针。this指针是一个隐式的指针,它指向调用非静态成员函数的对象。

示例

cpp 复制代码
#include <iostream>  
  
class MyClass {  
private:  
    int myVar; 
  
public:  
    MyClass(int value) : myVar(value) {}
  

    void printMyVar() {  
        std::cout << "The value of myVar for this object is: " << this->myVar << std::endl;  
        // this-> 可以不显式声明,编译器会自动为你处理.this->myVar可以改成myVar
    }  
  

    void setMyVar(int newValue) {  
        this->myVar = newValue; 
        // 使用this指针来引用当前对象的myVar 
    }  
};  
  
int main() {  
    MyClass obj1(10);
    MyClass obj2(20);
  
    obj1.printMyVar(); // The value of myVar for this object is: 10  
    obj2.printMyVar(); // The value of myVar for this object is: 20  
  
    obj1.setMyVar(30); 
    obj1.printMyVar(); // The value of myVar for this object is: 30  
    obj2.printMyVar(); // The value of myVar for this object is: 20,第二个对象的myVar保持不变  
  
    return 0;  
}

在这个例子中,MyClass类的两个成员函数:printMyVarsetMyVar都通过this指针来引用和修改当前对象的成员变量。

在类的成员函数内部中,通常不需要显式声明this指针,因为编译器会自动处理。然而,在某些情况下,可以显式地使用this指针,例如:

  • 通过this指针区分成员变量和参数。
  • 通过this指针返回调用对象本身,实现链式调用。

示例

cpp 复制代码
#include<iostream>
class MyClass {
private:
    int x;

public:
    MyClass(int value) : x(value) {}

    // 使用this指针来区分成员变量和参数
    void setValue(int x) {
        this->x = x; 
    }

    // 使用this指针返回调用对象本身
    MyClass& increment() {
        this->x++;
        return *this; // 返回*this即返回调用对象本身
    }

    int getValue() const {
        return x; 
    }
};

int main() {

    MyClass obj(5);
    obj.setValue(20);
    obj.increment().increment(); // 链式调用
    std::cout << obj.getValue() << std::endl; // 输出22

    return 0;
}

还可以定义一个MyClass*类型的指针,并将其初始化为this的值,从而在函数内部使用该指针来引用当前对象。这个指针本身不会"替代"this,只是一个额外的指针变量。

示例:

cpp 复制代码
class MyClass{
public:
    int value;

    MyClass(int v) : value(v) {}

    void printValue() {
        MyClass* self = this; // 定义一个MyClass*类型的指针self,并初始化为this
        std::cout << "The value of this object is: " << self->value << std::endl;
        // 现在可以使用self来引用当前对象,就像使用this一样
    }
};

这在设计特殊的数据结构(如前缀树)时候会用到。但在大多数情况下,简单地使用this就足够了。

静态成员

类的非静态成员(包括成员变量和成员函数)是类的每个对象所独有的。每一个类的对象会拥有自己独立的内存空间来存储其非静态成员变量的值,并通过this指针来与非静态成员函数进行关联。每个对象在调用非静态成员函数时,都会通过this指针传递自己的地址给该函数,以便函数能够访问和修改该对象的成员变量。

类的静态成员(包括静态成员变量和静态成员函数)在所有类的对象之间是共享的,只存在于一个数据存储区域。静态成员不与类的任何特定对象相关联。因此,静态成员函数内部没有this指针的概念。

静态数据成员: 在类的所有对象之间共享其值。在C++17之前,静态数据成员只能在类外进行初始化。C++17之后可以使用内联关键字inline在类内初始化静态数据成员。

类外初始化静态数据成员:

cpp 复制代码
class MyClass {
public:
    static int count; // 声明静态数据成员

    MyClass() {
        count++; 
    }

    ~MyClass() {
        count--; 
    }
};

// 在类外初始化静态数据成员
int MyClass::count = 0;

int main() {
    MyClass obj1; // 构造时,count 增加到 1
    MyClass obj2; // 构造时,count 增加到 2
    std::cout << MyClass::count << std::endl; // 输出 2
    return 0;
}

使用C++17新增的inline在类内初始化静态数据成员:

cpp 复制代码
#include <iostream>  
  
class MyClass {  
public:  
    // 使用内联变量语法在类内部声明并初始化静态数据成员
    inline static int count = 0;
  
    MyClass() {  
        count++;
    }  
  
    ~MyClass() {  
        count--; 
    }  
};  
  
int main() {  
    MyClass obj1; // 构造时,count 增加到 1  
    MyClass obj2; // 构造时,count 增加到 2  
    std::cout << MyClass::count << std::endl; // 输出 2  
    return 0;  
}

静态成员函数: 可以通过任何对象的实例或类名来调用,但是不能访问类的非静态成员。

cpp 复制代码
#include <iostream>  
#include <string>  
  
class MyClass {  
private:  
    int nonStaticVar; // 非静态成员变量  
    inline  static int staticVar = 42; // 静态成员变量
  
public:  
    MyClass(int value) : nonStaticVar(value) {}  
  
    // 静态成员函数  
    static void printStaticVar() {  
        std::cout << "The value of staticVar is: " << staticVar << std::endl;  
        // 尝试通过静态成员函数访问非静态成员变量会导致编译错误  
        // std::cout << "The value of staticVar is: " << nonStaticVar << std::endl;  
    }  

       
    // 非静态成员函数  
    void printVars() {  
        std::cout << "The value of staticVar is: " << staticVar << std::endl;  
        std::cout << "The value of nonStaticVar is: " << nonStaticVar << std::endl;  
    }  
};  
  

  
int main() {  
    MyClass obj(10);  
  
    // 通过类名调用静态成员函数  
    MyClass::printStaticVar();   // The value of staticVar is: 42 
  
    // 通过对象实例调用静态成员函数
    obj.printStaticVar();  // The value of staticVar is: 42 
  
    // 调用非静态成员函数  
    obj.printVars();   
    // The value of staticVar is: 42   
    //The value of nonStaticVar is: 10

    return 0;  
}
相关推荐
娅娅梨6 分钟前
C++ 错题本--not found for architecture x86_64 问题
开发语言·c++
兵哥工控11 分钟前
MFC工控项目实例二十九主对话框调用子对话框设定参数值
c++·mfc
我爱工作&工作love我18 分钟前
1435:【例题3】曲线 一本通 代替三分
c++·算法
娃娃丢没有坏心思1 小时前
C++20 概念与约束(2)—— 初识概念与约束
c语言·c++·现代c++
lexusv8ls600h1 小时前
探索 C++20:C++ 的新纪元
c++·c++20
lexusv8ls600h1 小时前
C++20 中最优雅的那个小特性 - Ranges
c++·c++20
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
好睡凯1 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
依旧阳光的老码农2 小时前
标准C++ 字符串
开发语言·c++
白-胖-子2 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-成绩排序
c++·算法·蓝桥杯·真题·蓝桥等考