1. 静态成员定义
由关键字static修饰类体中成员,称为类静态成员。类的静态成员为其所有对象共享,不管有多少对象,静态成员只有一份存于公用内存中。静态数据成员被当作该类类型的全局对象。
2. 静态属性
在类设计中,用关键字static修饰的数据成员为静态数据成员。有该类型实例化的所有对象,共享系统为静态成员分配的一个存储空间,而这个存储空间是程序执行main函数之前分配的,在实例化对象时不再为静态成员分配空间(静态成员数据不在对象空间中)。
2.1 设计静态数据成员目的是信息共享
例:
class circle
{
private:
double pi;
double radius;
public:
circle(double r = 0.0) :pi(3.14), radius(r)
{
}
~circle() { }
void area() const
{
cout << pi * radius * radius << endl;
}
};
int main()
{
circle cir(10.00);
cir.area();
size_t sz = sizeof(cir);
cout << sz << endl;
return 0;
}
运行结果: 其中,带参的构造函数初始化时,只能circle(double r = 0.0) :pi(3.14), radius?,因为构造函数在构建对象时,调用一次构建一次,如果直接在private中写出double pi = 3.14,这样的话,每次都会去构建,因此,就需要考虑静态关键字去构建数据成员,程序变为: 注意:在类circle中私有部分用静态关键字static声明,然后在类外对静态成员pi进行定义,如上述程序中的double circle::pi = 3.14; 下面这个虽然是对的,但是没必要,因为前面已经用静态关键字声明过: 总结: 同全局变量相比,使用静态数据成员有两个优势: ①静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性; ②可以实现信息隐藏,静态成员可以是private成员,而全局变量不能。
2.2 静态数据是该类所有对象共有的
静态数据是该类所有对象所共有的,可提供同一类型的所有对象之间,信息共享或信息交换的一种方式。 静态数据成员属于整个类型,使用时可用以下格式: 类名::静态数据成员名或对象.静态数据成员名(前提是可访问符为public)。 例:
class Cat
{
private:
static int num;
private:
std::string _owner;
std::string _name;
public:
Cat(const string& ow, const string &na):_owner(ow),_name(na)
{
num += 1;
cout << "Create Cat: " << num << endl;
}
~Cat()
{
num -= 1;
cout << "Destroy Cat: " << num << endl;
}
};
int Cat::num = 0;
int main()
{
Cat ca("yhp", "pt");
Cat cb("hm", "bl");
return 0;
}
运行结果: 在这个程序中,static int num,是共有的,但是定义的话,在类外进行定义,前面只需要进行声明就行了。
2.3 静态数据成员之前没有this
在类的成员函数中使用静态数据成员,静态数据成员之前没有this。 例:
class Cat
{
private:
static int num;
private:
std::string _owner;
std::string _name;
public:
Cat(const string& ow, const string& na) :_owner(ow), _name(na)
{
num += 1;
cout << "Create Cat: " << num << endl;
}
~Cat()
{
num -= 1;
cout << "Destroy Cat: " << num << endl;
}
void Print() const
{
cout << "Owner: " << _owner << " Name: " << _name << endl;
num += 1;
}
};
int Cat::num = 0;
int main()
{
Cat ca("yhp", "pt");
ca.Print();
Cat cb("hm", "bl");
cb.Print();
return 0;
}
运行结果: 注意,num之所以可以+=1是因为没有this指针。 静态数据成员的类型可以是其所属类型,而非static数据成员只能被声明为该类的指针。
2.4 总结
①设计静态数据成员目的是信息共享和信息交流; ②类的静态数据成员为所有类对象所共享,不属于某个具体的实例; ③类的静态数据成员必须在类外定义,定义时不添加static关键字,不能在构造函数的初始化列表中创建,因为每调用一次构建函数创建一次对象,但是ststic出现的时候,不管调不调用,都会有创建对象存在; ④类的静态数据成员类型是int,short,char,long long,并且是const,可以在类中直接初始化,也可以在类外初始化;如: ⑤在类的成员函数中使用静态数据成员,静态数据成员之前是没有this指针的; ⑥当类的静态成员为公有时,可以在外部函数使用:类名::静态数据成员名或对象.静态数据成员名,也可以在类体中定义自身的静态类型对象。
3. 静态方法
函数成员说明为静态,将与该类的不同对象无关;静态函数成员的调用,在对象之外可以采用下面的方式: 类名::函数名或对象名.函数名; 与静态数据成员相反,为使用方便,静态函数成员多为公有。 例:
class Object
{
private:
static int num;
private:
int value;
public:
Object(int val) :value(val)
{
num = 1;
}
void Print()
{
cout << "value: " << value << " num: " << num << endl;
}
static void fun(Object& obj)
{
cout << obj.value << " " << num << endl;
}
};
int Object::num = 0;
其中静态函数没有this指针 静态成员函数没有this指针,因此在静态成员函数显式地使用this指针都将导致编译时出现错误,试图访问隐式使用this指针所指向的非静态数据成员也会导致编译时出现错误。 总结: 一个常规的成员函数声明描述了三件在逻辑上相互不同的事: (1)该函数能访问类声明的私有部分 (2)该函数位于类的作用域之中 (3)该函数必须经由一个对象去激活(有一个this指针) 将一个函数声明为友元可以使它具有第(1)种属性;将一个函数声明为static可以使它只具有第一种和第二种性质;
4. static不在类中使用时的特点
(1)构建临时变量时,如 普通静态变量,函数中创建并且创建之后结束,而局部静态变量,在函数结束时生存期结束,但是可见性只在当前fun函数中。 (2)构建全局变量时,如 静态全局变量,在程序结束时生存期结束,而且只在本文件中使用,不可多文件使用,就算在另一个文件中用extern关键字,也不行,因为其可见性就在本函数;但是普通全局变量,不加静态关键字static,其他文件用extern关键字可以使用。
|