文章目录
- this指针和静态成员
- this指针
- 静态成员
this指针和静态成员
this指针
C++中类的成员变量和成员函数的存储方式有所不同:
- 成员变量:对象的成员变量直接作为对象的一部分存储在内存中。
- 成员函数:成员函数(非静态成员函数)不直接存储在对象的内存中。它们的代码(即函数体中的指令)存储在代码区中。
当我们创建一个类的多个对象时,这些对象的成员函数的代码是共享的,也就是说,无论我们创建多少个类的对象,这些函数的代码都只有一份。 但是,每个对象都有自己独立的成员变量。为了在这些共享的成员函数内部引用和修改特定对象的成员变量,C++提供了this
指针。this
指针是一个隐式的指针,它指向调用非静态成员函数的对象。
示例:
#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
类的两个成员函数:printMyVar
和setMyVar
都通过this
指针来引用和修改当前对象的成员变量。
在类的成员函数内部中,通常不需要显式声明this
指针,因为编译器会自动处理。然而,在某些情况下,可以显式地使用this
指针,例如:
- 通过
this
指针区分成员变量和参数。 - 通过
this
指针返回调用对象本身,实现链式调用。
示例
#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
,只是一个额外的指针变量。
示例:
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
在类内初始化静态数据成员。
类外初始化静态数据成员:
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
在类内初始化静态数据成员:
#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;
}
静态成员函数: 可以通过任何对象的实例或类名来调用,但是不能访问类的非静态成员。
#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;
}