一、静态成员
1.1静态数据成员
被类的实例共享,而不是某个特定类对象
静态数据成员的作用域和初始化
用关键字 static 声明
- 可以被声明为 public, private, protected
- 当声明类的数据成员为静态时,无论创建多少个类的对象,静态成员都只有一个副本
- 在类的所有对象中共享,具有静态生存期
- 基本数据类型的的静态数据成员默认情况初始化为零
- 类内声明,类外定义和初始化并用范围解析运算符(::)指明所属的类。int, enum 类型的 const static 数据成员可以在类定义中声明时初始化
- 具有默认构造函数的类类型的静态数据成员(即静态成员对象)不必初始化,其默认构造函数会被调用
访问静态数据成员
通常通过类的静态成员函数或类的友元访问类的 private, protected 静态成员
当类没有对象时
- 要访问 public 静态数据成员,需在成员名前加类名和二元作用域运算符(::)
- 要访问 private, protected 静态数据成员,需提供 public 静态成员函数,并通过在函数名前加类名和二元作用域运算符(::)调用函数
1.2静态成员函数
把成员函数声明为静态的,就可以把函数与类的任何特定对象独立开来
- 在类对象不存在的情况下也能被调用,使用类名加范围解析运算符 :: 即可访问
- 静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数
- 静态成员函数有一个类范围,不能访问类的 this 指针,可以使用静态成员函数来判断类的某些对象是否已被创建
- 用静态成员函数访问非静态成员,需通过对象
#include <iostream>
using namespace std;
class Box {
public:
static int count; //若该静态数据成员在private部分声明,则只能通过静态成员函数处理
Box(double l, double b, double h);
double Volume();
static int getCount();
private:
double length, width, height;
};
int Box::count = 0;
Box::Box(double l = 2.0, double b = 2.0, double h = 2.0) {
cout <<"One constructor was called." << endl;
length = l, width = b, height = h;
count++;
}
double Box::Volume() {
return length * width * height;
}
int Box::getCount() { //静态成员函数
return count;
}
int main(void) {
//在创建对象之前输出对象的总数
cout << "Inital Stage Count: " << Box::getCount() << endl;
Box Box1(3.3, 1.2, 1.5);
Box Box2(8.5, 6.0, 2.0);
//在创建对象之后输出对象的总数
cout << "Final Stage Count: " << Box::getCount() << endl;
return 0;
}
结果:
Inital Stage Count: 0
One constructor was called.
One constructor was called.
Final Stage Count: 2
注:
静态成员函数与普通成员函数的区别
- 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)
- 普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针
使用静态成员了解构造与析构函数的调用情况
#include <iostream>
using namespace std;
class Cpoint {
public:
static int value;
static int num;
Cpoint(int x,int y) {
xp = x, yp = y;
value++;
cout << "调用构造:" << value << endl;
}
~Cpoint() { num++; cout << "调用析构:" << num << endl; }
private:
int xp, yp;
};
class CRect {
public:
CRect(int x1,int x2) : mpt1(x1,x2), mpt2(x1,x2) { cout << "调用构造\n"; }
~CRect() { cout << "调用析构\n"; }
private:
Cpoint mpt1, mpt2;
};
int Cpoint::value=0;
int Cpoint::num=0;
int main() {
CRect p(10,20);
cout << "Hello, world!" << endl;
return 0;
}
结果:
调用构造:1
调用构造:2
调用构造
Hello, world!
调用析构
调用析构:1
调用析构:2
二、this指针
每个对象可通过一个称为 this 的指针访问自己的地址
- 对象的指针不是对象本身的一部分,即 this 所占的内存不会在对对象进行 sizeof 操作的结果中体现
- this 指针作为隐式的实参传递给对象的各个非 static 成员函数
- static 成员函数没有 this 指针,因为 static 数据成员和 static 成员函数独立于类的任何对象而存在,而 this 指针必须指向特定的类对象
- this 指针的类型取决于对象的类型和使用 this 指针的成员函数是否声明为 const
- this 指针可以防止对象赋值给自己
#include<iostream>
using namespace std;
class Test {
public:
Test(int = 0);
void print();
private:
int x;
};
Test::Test(int value) : x(value) { }
void Test::print() {
cout << "\tx = " << x
<< "\nthis -> x = " << this -> x
<< "\n(*this).x = " << (*this).x << endl;
}
int main() {
Test test(20);
test.print();
return 0;
}
结果:
x = 20
this -> x = 20
(*this).x = 20