(1)static,C语言中有2种用法:static修饰局部变量和全局变量,含义完全不同
(2)static,C++中扩展了第3种用法:静态类、静态成员,含义和前2种完全不同
(1)用static修饰成员变量,即为静态成员变量;用static修饰成员方法,即为静态成员方法
(2)静态成员属于class本身,而不属于对象
(1)静态成员变量在类的多个对象中均可访问,且是同一个实体,被多个对象“共享”。
(2)静态成员变量和方法可以用对象调用,也可以根本不产生对象而用类本身来调用。
1、静态方法只能访问静态成员
2、静态方法中不可以定义this,super关键字
因为静态优先于对象存在,所以静态方法中不可以出现this
(3)静态成员函数在类外实现时只需在类内声明时加static,类外实体无须加static关键字,否则是错误的(思考下为什么?)
修改了函数的链接属性,将函数变为一个静态函数
#include
using namespace std;
class sample
{
public:
int age; //普通成员变量
static int flag;//静态成员变量
void print(void);
static void test(int t);
private:
};
void sample::print(void)
{
cout << "age = " <<this->age << endl;
cout << "flag = " << this->flag << endl;
}
void sample::test(int age)
{
cout << "this is a test function." << endl;
cout << flag << endl;//不可以使用this->flag
cout << sample::flag << endl;
cout << age << endl;
//cout << age << endl;//非静态成员引用必须与特定对象相对,这个报错,静态方法只能访问静态成员
}
int sample::flag = 0;//静态成员变量与普通成员变量的不同之处,否则该类的对象无法使用该变量
//void sample::test(void);//静态成员方法不需要这样,虽然写了编译也不会报错
int main(int argc, char *argv[])
{
sample s1, s2;
s1.flag = 2;
s1.age = 21;
s1.print();
s1.test(s1.age);
s2.age = 22;
s2.print();
s2.test(s2.age);
sample::flag = 666;
return 0;
}
(1)静态数据成员不能在类中初始化,因为类定义实际只是模型,本身并没有和变量/对象实体去关联
(2)静态数据成员不能在类的构造函数中初始化,因为构造函数是用来构造具体单个对象的,而静态成员属于类(或者说类和他的所有对象共享),如果在构造函数中允许对静态成员初始化或赋值,就会每多创建一个对象,原有对象中该静态成员的值莫名其妙变了,不合理
(3)静态数据成员不能用初始化列表方式来初始化
(4)静态数据成员如果不初始化则值默认为0
(5)静态成员仍然遵循public,private,protected访问准则。
(1)普通成员函数中可以调用静态成员变量和方法,调用方法有3种:直接访问、this指针访问、类名::func()方式访问
(2)静态方法中只能访问静态成员变量和方法,不能访问任何非静态的东西
(3)静态方法中如果确实需要访问非静态成员,应该通过函数传参方式
(1)class定义时只是定义类型,并不定义变量和对象,静态成员变量真正定义是在外部,类似于全局变量
(2)静态成员变量在编译链接时分配,程序加载时被落实到内存中,程序结束时死亡,等同于全局变量
(3)静态成员函数在编译链接时分配,程序加载时被落实到内存中,程序结束时死亡,类似于全局函数
(4)普通成员和对象绑定,随对象的创建和释放而生死(不管在栈里还是堆里),类似于局部变量和malloc堆内存
(5)静态成员变量在对象中不占用存储空间
(1)静态数据成员的用途之一是统计有多少个对象实际存在,比如声明一个学生类,其中一个成员为学生总数,则这个变量就应当声明为静态变量,应该根据实际需求来设置成员变量。
#include
using namespace std;
class student
{
public:
string name;
int age;
int grade;
static int cnt;
student()
{
this->name = "student";
this->age = 0;
this->grade = 0;
student::cnt++;
}
~student()
{
student::cnt--;
}
static void print(void)
{
cout << "The number of students is " << student::cnt << endl;
}
private:
};
int student::cnt;
int main(int argc, char *argv[])
{
student p1;
p1.print();
student p2;
p2.print();
return 0;
}
(2)静态方法就是与该类相关的,是类的一种行为,而不是与该类的实例对象相关
(1)静态成员仍然在class内,仍可通过对象调用,因此表面上遵守面向对象规则。
(2)静态成员一定程度上破坏了面向对象,因为没有对象直接用class名也可以调用静态成员。
(3)静态成员可被看做是类外部的全局变量和全局函数被封装到了类的内部
(4)一个类的静态成员和非静态成员是完全不同的,两者唯一的关联可能就是隶属于同一个class的作用域内。
(1)class声明时使用static,整个类是个静态类
(2)静态类内部全是静态成员,没有非静态成员
(3)静态类不能被实例化
(4)静态类是密封(sealed)的。 补充:什么是密封?
(5)静态类不包括构造函数
(6)静态类不能指定任何接口实现,不能有任何实例成员
(7)静态类的成员不能有protected或protected internal访问保护修饰符。
(8)静态类不能包含构造函数,但仍可声明静态构造函数以分配初始值或设置某个静态状态。
(1)编译器能够执行检查以确保不致偶然地添加实例成员。编译器将保证不会创建此类的实例。
(2)静态类是密封的,因此不可被继承。
(1)Java/C#等高级语言支持静态类,而C++并不支持。
(2)C++中创建静态类与创建仅包含静态成员和私有构造函数的类大致一样。私有构造函数阻止类被实例化。
注:本文章参考了《朱老师物联网大讲堂》课程笔记,并结合了自己的实际开发经历以及网上他人的技术文章,综合整理得到。如有侵权,联系删除!水平有限,欢迎各位在评论区交流。