文章目录
前言
静态成员的访问方式
无论是静态成员变量还是静态成员函数,都是三种访问方式
通过对象访问
通过对象指针访问
通过类名访问
#include <iostream>
using namespace std;
class Car {
public:
static int ms_count;
static Car* ms_Car;
static int getCount() {
return ms_count;
}
static Car* sharedCar() {
return ms_Car;
}
};
int Car::ms_count = 0;
Car* Car::ms_Car = NULL;
int main()
{
//通过对象访问
Car car0;
car0.ms_count = 100;
cout << car0.getCount() << endl;
//通过对象指针访问
Car* p = new Car();
p->ms_count = 200;
cout << p->getCount() << endl;
cout <<"p:"<< p << endl;
//ms_Car本身是对象指针
p->ms_Car = p;
cout <<"p->sharedCar():"<< p->sharedCar() << endl;
//通过类名访问
Car::ms_count = 300;
cout << Car::getCount() << endl;
return 0;
}
out为
100
200
p:017DE620
p->sharedCar():017DE620
300
静态成员函数的特征
静态成员函数不能是虚函数
虚函数只能是非静态成员函数
因为虚函数应用于多态,多态是父类指针指向子类对象,牵扯到对象了,所以不能
静态成员函数内部只能访问静态成员
静态成员函数内部只能访问静态成员变量/函数,不能访问非静态成员变量/函数
因为非静态成员变量/函数在创建对象的时候才存在
而静态成员可以直接通过类调用,可能压根没有对象
下面是一些例子:
静态成员函数不能访问非静态成员变量/函数
静态成员函数可以通过对象访问非静态成员变量
静态成员函数可以通过对象访问非静态成员函数
静态成员函数可以访问静态成员变量/函数
非静态成员函数内部可以访问静态成员
非静态成员函数只在创建对象的时候存在,不可通过类访问
非静态成员函数内部可以访问静态成员变量/函数
代码
#include <iostream>
using namespace std;
class Car {
public:
int m_count;
static int ms_count;
static Car* ms_Car;
static int getCount() {
return ms_count;
Car car0;
car0.m_count = 10;
car0.test();
}
static Car* sharedCar() {
return ms_Car;
}
void test() {
//非静态成员函数内部可以访问静态成员
ms_count = 12;
cout << "ms_count:"<< ms_count << endl;
cout << "getCount():" << getCount() << endl;
}
};
int Car::ms_count = 0;
Car* Car::ms_Car = NULL;
int main()
{
//通过类名访问
Car::ms_count = 300;
cout << Car::getCount() << endl;
Car car1;
car1.test();
return 0;
}
out为
300
ms_count:12
getCount():12
构造函数、析构函数不能是静态
当声明和实现分离时,实现部分不能带static
全局变量与静态成员变量的内存都放在全局区
代码
#include <iostream>
using namespace std;
class Car {
public:
int m_count;
static int ms_count;
static Car* ms_Car;
};
int Car::ms_count = 0;
Car* Car::ms_Car = NULL;
int g_count;//全局变量
int main()
{
Car car0;
car0.m_count = 1;
car0.ms_count = 2;
g_count = 3;
return 0;
}
汇编代码
18: Car car0;
19: car0.m_count = 1;
00E92138 mov dword ptr [ebp-8],1 //赋值给栈空间 ebp是栈空间
20: car0.ms_count = 2;
00E9213F mov dword ptr ds:[00E9C70Ch],2 //赋值给数据段
21:
22: g_count = 3;
00E92149 mov dword ptr ds:[00E9C714h],3 //赋值给数据段
23:
24:
25: return 0;
ds就是data segment的简写,就是数据段,即全局区
静态成员变量地址是唯一的
通过子类和父类访问的静态成员变量地址是一样的
代码
#include <iostream>
using namespace std;
class Car {
public:
int m_count;
static int ms_count;
static Car* ms_Car;
};
int Car::ms_count = 0;
Car* Car::ms_Car = NULL;
class BigCar : public Car {
};
int main()
{
cout << &Car::ms_count << endl;
cout << &BigCar::ms_count << endl;
return 0;
}
out为
00ACC70C
00ACC70C
汇编为【可以看出,通过父类访问静态成员变量和通过子类访问静态成员变量的汇编是一样的】
20: cout << &Car::ms_count << endl;
00AC1A78 mov esi,esp
00AC1A7A push 0AC14E7h
00AC1A7F mov edi,esp
00AC1A81 push 0ACC70Ch
00AC1A86 mov ecx,dword ptr ds:[00ACD0DCh]
00AC1A8C call dword ptr ds:[00ACD0A0h]
00AC1A92 cmp edi,esp
00AC1A94 call 00AC12FD
00AC1A99 mov ecx,eax
00AC1A9B call dword ptr ds:[00ACD0A8h]
00AC1AA1 cmp esi,esp
00AC1AA3 call 00AC12FD
21: cout << &BigCar::ms_count << endl;
00AC1AA8 mov esi,esp
00AC1AAA push 0AC14E7h
00AC1AAF mov edi,esp
00AC1AB1 push 0ACC70Ch
00AC1AB6 mov ecx,dword ptr ds:[00ACD0DCh]
00AC1ABC call dword ptr ds:[00ACD0A0h]
00AC1AC2 cmp edi,esp
00AC1AC4 call 00AC12FD
00AC1AC9 mov ecx,eax
00AC1ACB call dword ptr ds:[00ACD0A8h]
00AC1AD1 cmp esi,esp
00AC1AD3 call 00AC12FD