C++的static、this和final关键字介绍
☆static关键字:static可以用于不同的上下文,其主要作用如下:
在类中,static成员表示类的静态成员,即属于整个类而不是类的实例。静态成员可以被所有该类的对象所共享,且不依赖于特定的对象。静态成员变量存储在数据段,静态成员函数不依赖于实例,可以直接通过类名调用。
在函数内部,static局部变量或函数表示在函数执行期间只初始化一次,并在多次调用之间保持其值。
在全局或命名空间作用域中,static限制符将标识符的可见性限制为当前文件或当前命名空间。
☆this关键字:this是一个指向当前对象的指针,它在类的成员函数中使用。当一个对象调用它自己的成员函数时,编译器会隐式地传递一个指向该对象的指针给成员函数。通过使用this指针,可以在成员函数内部访问和操作当前对象的成员变量和成员函数。
☆final关键字:final关键字C++11引入到语言中,主要用于类和成员函数的声明中,具有以下含义:
在类声明中,final关键字用于禁止继承。如果一个类被声明为final,则其他类不能从该类派生。
在成员函数声明中,final关键字用于阻止派生类对该成员函数进行重写(override)。如果一个成员函数被声明为final,则派生类不能重写该函数。
static关键字
当我们讨论C++中的static关键字时,可以通过以下几个方面的例子来说明其用法和含义:
1.静态变量的使用
静态变量是在程序运行期间只分配一次内存空间,并且其值在多次调用中保持不变。静态变量在函数内部使用static关键字声明,在函数外部定义。例如:
#include <iostream>
using namespace std;void foo() {static int count = 0; // 声明一个静态变量count++;cout << "foo 被调用了 " << count << " 次" << endl;
}int main() {foo(); // 输出:foo 被调用了 1 次foo(); // 输出:foo 被调用了 2 次return 0;
}
在上面的例子中,count是一个静态变量。每次调用foo()函数时,count的值会自增,并且在函数调用之间保持不变。这意味着count的值在多次函数调用间被共享。
2. 静态成员函数的使用
静态成员函数属于整个类而不是某个对象实例,因此可以通过类名直接调用,无需创建对象实例。静态成员函数没有this指针,因此不能访问非静态成员。例如:
#include <iostream>
using namespace std;class MyClass {
public:static void staticFunc() {cout << "这是一个静态函数" << endl;}
};int main() {MyClass::staticFunc(); // 直接通过类名调用静态函数return 0;
}
在上述示例中,staticFunc()是一个静态函数。我们可以直接使用类名和作用域解析运算符来调用它,而无需创建类的实例。
3. 静态数据成员的使用:
在静态数据成员的使用过程中,不需要先创建类的实例,而是直接通过类名访问该成员。例如:
#include <iostream>
using namespace std;class MyClass {
public:static int count; // 声明一个静态数据成员
};int MyClass::count = 0; // 静态数据成员的定义和初始化int main() {MyClass obj1;MyClass obj2;obj1.count++;obj2.count++;cout << "obj1 的 count 值为:" << obj1.count << endl; // 输出:2cout << "obj2 的 count 值为:" << obj2.count << endl; // 输出:2return 0;
}
4. 静态局部变量的使用
静态局部变量是在函数内部声明的,但它们与普通局部变量不同。静态局部变量在程序运行期间只被初始化一次,并且在函数调用之间保持其值。示例:
#include <iostream>
using namespace std;void func() {static int count = 0; // 声明静态局部变量count++; // 在每次函数调用时增加count的值cout << "Count: " << count << endl;
}int main() {func(); // 输出:Count: 1func(); // 输出:Count: 2func(); // 输出:Count: 3return 0;
}
在上述代码中,函数func()内部声明了一个静态局部变量count,并将其初始值设置为0。每次调用func()函数时,静态局部变量count的值会自增,并打印出当前的值。由于静态局部变量只在编译时初始化一次,因此在多次调用func()函数时,count的值得以保留并递增。
需要注意的是,静态局部变量的生命周期从其声明处开始,一直到程序结束才终止。另外,静态局部变量的作用域仅限于声明它的函数内部。此外,请注意静态局部变量的初始值只在第一次声明时起作用,在后续调用中将被忽略。
5.在文件作用域中声明静态变量或函数
当我们在函数外定义一个变量或函数,并且在前面使用static关键字进行修饰时,将限制其在当前文件范围内可见。这样做可以避免与其他文件中具有相同名称的全局变量或函数发生冲突。
1)静态变量的文件作用域声明:
// File1.cpp
static int count = 0; // 在文件作用域中声明一个静态变量// File2.cpp
extern int count; // 使用 extern 关键字来引用另一个源文件中的静态变量int main() {count++; // 访问和修改静态变量return 0;
}
在上面的示例中,count是在File1.cpp文件的文件作用域中声明的静态变量。通过使用static关键字,我们限制了count的作用范围仅在当前源文件中。然后,在File2.cpp文件中,我们使用extern关键字来引用count变量,以便在main()函数中访问和修改它。
2)静态函数的文件作用域声明:
// File1.cpp
static void staticFunc() { // 在文件作用域中声明一个静态函数cout << "这是一个静态函数" << endl;
}// File2.cpp
extern void staticFunc(); // 使用 extern 关键字来引用另一个源文件中的静态函数int main() {staticFunc(); // 调用静态函数return 0;
}
在上述示例中,staticFunc()是在File1.cpp文件的文件作用域中声明的静态函数。通过使用static关键字,我们限制了函数的作用范围仅在当前源文件中。然后,在File2.cpp文件中,我们使用extern关键字来引用staticFunc()函数,以便在main()函数中调用它。
This关键字
C++中的this关键字用于表示当前对象的指针。它可以在类的成员函数中使用,代表调用该成员函数的对象的地址。
this指针是一个隐式参数,它是每个成员函数中都可以使用的指针。this指针指向调用该函数的对象的地址。我们可以使用this指针来访问当前对象的成员变量和成员函数。例子:
#include <iostream>
using namespace std;class MyClass {
public:void printAddress() {cout << "对象地址: " << this << endl;}
};int main() {MyClass obj;obj.printAddress(); //调用printAddress函数,并传递当前对象的地址return 0;
}
在上述示例中,printAddress函数中的this指针表示调用该函数的obj对象的地址。通过输出this的值,我们可以得到当前对象的地址。
再给出一个例子:
#include <iostream>
using namespace std;class MyClass {
private:int value;public:void setValue(int val) {this->value = val; // 使用 this 指针访问成员变量}int getValue() {return this->value; // 使用 this 指针返回成员变量的值}
};int main() {MyClass obj;obj.setValue(42);cout << "Value: " << obj.getValue() << endl;return 0;
}
在上述示例中,setValue()函数使用this指针来访问成员变量value并将其设置为参数val的值。getValue()函数也使用this指针来返回成员变量的值。
注意,this指针只能在非静态成员函数中使用,因为静态成员函数没有隐式的对象指针。而且,在全局函数或静态成员函数中不能使用this指针。
通过使用this关键字,我们可以在成员函数中准确地引用当前对象的成员,并且能够避免命名冲突或歧义。
final 关键字
final关键字是在C++11标准中引入的。它用于限制类、成员函数和虚函数的继承和重写。
1. 对于类:
在类声明中,使用final关键字可以防止该类被继承。例如:
class Base final { // 使用 final 关键字禁止继承// ...
};class Derived : public Base { // 错误!不能从 final 类派生// ...
};
2. 对于成员函数:
在成员函数声明中,使用final关键字可以防止该函数在派生类中被重写(override,覆盖)。例如:
class Base {
public:virtual void foo() final { // 使用 final 关键字禁止重写// ...}
};class Derived : public Base {
public:void foo() override { // 错误!不能重写 final 函数// ...}
};
3. 对于虚函数:
在虚函数声明中,使用final关键字可以防止派生类中的进一步重写。例如:
class Base {
public:virtual void foo() { // 虚函数可重写// ...}virtual void bar() final { // 使用 final 关键字禁止进一步重写// ...}
};class Derived : public Base {
public:void foo() override { // 可以重写基类的虚函数// ...}void bar() { // 错误!不能重写 final 虚函数// ...}
};
ok!