class Circle
{
private:
double r; //半径
double pi; //圆周率
public:
Circle( double _r, double _pi ) : r(_r), pi(_pi)
{}
double get_area() //计算面积
{
return r*r*pi;
}
};
int main()
{
Circle c1( 2.0, 3.14 );
Circle c2( 1.9999, 3.141592 );
// c1.get_area() c2.get_area()
}
c2圆的半径要小,但是计算出来的面积却要大一些
这个bug的原因在于 两个圆的圆周率pi没有统一
double pi; //圆周率, 不应该是属于某个对象的,而是应该属于这个Circle类的
在设计这个类的时候,有些数据成员,不应该属于某个对象,而应属于这个类的所有的对象
"属于这个类的"
该如何设计呢?
---> "类的静态成员"
1.类的静态成员
1)什么是静态成员?
为了实现类的对象之间的数据共享,同时又能够保证数据的安全, C++提出了静态成员的概念
一个类的所有对象之间共享的数据, 而不是所有对象共享的数据(其他类的对象不能共享的)
保证数据的安全(不能让别人随意修改)
在一个类的声明中, 用 static 修饰 类的成员 ,称之为 类的静态成员
静态成员变量(静态数据成员)
静态成员函数
例子:
class Circle
{
private:
double r;
static double pi; //圆周率 类的 静态成员变量
public:
static void set_pi(double _pi) //修改圆周率pi 类的 静态成员函数
{
pi = _pi;
}
double get_area() //计算面积
{
return r*r*pi;
}
};
2)静态成员的含义
静态成员 不属于某个对象,而是属于这个类的所有的对象 "属于这个类的"
也就是说 静态成员不管这个类有多个对象(0个或者多个),静态成员只有一份拷贝
静态成员 属于这个类的所有对象共享的
静态成员 又是这个类的所有对象都可以使用的
在这个类的第一个对象创建之前, 所有的静态成员都必须初始化(定义)
why? 因为这个类的第一个对象,一开始就有可能使用到这个静态成员(如:在构造函数中)
如何做到 在创建类的第一个对象之前 就初始化这个静态成员呢?
3)静态数据成员的初始化
(1)静态数据成员的初始化, 必须放在类外 "类似于C语言中全局变量的初始化"
静态数据成员的定义(初始化)格式如下:
类型 类名::静态成员变量名 = 初始值;
例子:
double Circle::pi = 3.14; //Circle类 的静态数据成员pi 的初始化
(2)静态数据成员的访问
类名::静态成员名
也可以通过 对象名和对象指针 去访问静态成员
例子:
class Circle
{
private:
double r;
static double pi; //圆周率 类的 静态成员变量
public:
Circle( double _r ) : r(_r)
{}
double get_area() //计算面积
{
return r*r*pi;
}
};
//Circle类 的静态数据成员pi 的初始化
double Circle::pi = 3.14;
int main()
{
Circle c1( 2.0 );
Circle c2( 1.9999 );
cout << c1.get_area() << endl;
cout << c2.get_area() << endl;
cout << sizeof(c1) << endl; // 8 只存放属于这个对象的非static数据成员
}
4)静态成员函数
加了 static修饰的成员函数, 称之为 类的静态成员函数
static void set_pi(double _pi) //修改圆周率pi 类的 静态成员函数
{
pi = _pi;
}
static成员函数 和 非static成员函数 的区别:
(1)含义上的区别
加了static修饰的成员函数,属于这个类的,不加static修饰的成员函数属于对象
static成员函数 没有this指针
在static成员函数中, 不能访问非static数据成员 (非static数据成员属于对象)
"某某对象的..." this->非static成员
例子:
(2)访问方式的区别
static void set_pi( double _pi ) //类的静态成员函数
{
pi = _pi;
//r = 5.0; //error 在static成员函数中, 不能访问非static数据成员
//没有this指针
}
类的非static成员函数, 属于对象, 只能通过 "对象名/对象指针" 去访问
类的static成员函数, 属于这个类的,同时也是属于这个类的所有对象的
可以通过 "类名::函数名"去访问, 也可以通过"对象名/对象指针" 去访问
例子:
class Circle
{
private:
double r;
static double pi; //圆周率 类的 静态成员变量
public:
Circle( double _r ) : r(_r)
{}
static void set_pi( double _pi ) //类的静态成员函数
{
pi = _pi;
//r = 5.0; //error 在stati成员函数中, 不能访问非static数据成员
//没有this指针
}
double get_area() //计算面积
{
return r*r*pi;
}
};
//Circle类 的静态数据成员pi 的初始化
double Circle::pi = 3.14;
int main()
{
Circle c1( 2.0 );
Circle c2( 1.9999 );
cout << c1.get_area() << endl;
cout << c2.get_area() << endl;
//静态成员函数的访问
//c1.set_pi( 3 );
//c2.set_pi( 2 );
Circle::set_pi( 4 ); // 类名::静态成员函数名
cout << c1.get_area() << endl;
cout << c2.get_area() << endl;
}
类的非static成员函数,第一个参数其实是隐含的 this指针
类的static成员函数, 没有this指针
类的非static成员函数内部,可以访问非static成员(属于特定的对象的 this)
也可以访问static成员(属于这个类的所有对象的)
类的static成员函数内部, 不可以访问非static成员的
只能访问 类的static成员
=================================
const 只读的
const修饰类的成员函数
表示在该成员函数中 不能对象类的任何成员进行修改
类的非static成员函数 后面可以用const修饰
类的static成员函数 不能用const修饰 (const其实修饰的this)
例子:
class Circle
{
private:
double r;
static double pi; //圆周率 类的 静态成员变量
public:
Circle( double _r ) : r(_r)
{}
static void set_pi( double _pi ) //类的静态成员函数
{
pi = _pi;
//r = 5.0; //error 在stati成员函数中, 不能访问非static数据成员
//没有this指针
}
double get_r() const //const修饰的成员函数,在该成员函数内部不能对类的任何成员进行修改
{
//r = 3.0; //error
return r;
}
/*
==>
double get_r( const Circle *this ) //const修饰其实是this
{
return this->r;
}
*/
double get_area() //计算面积
{
return r*r*pi;
}
};
//Circle类 的静态数据成员pi 的初始化
double Circle::pi = 3.14;
5)静态成员的访问
(1)通过static成员函数 去访问 static数据成员 (建议)
(2) 能不能通过 非static成员函数 去访问 static数据成员呢?
当然也可以
(3) 能不能通过 static成员函数 去访问 非static数据成员呢?
不可以, 没有this指针
思考:
static关键字的作用?
(1) static修饰局部变量, 延长对象的生存期, 变为随进程的持续性, 并且静态局部变量只会初始化一次
(2) static修饰全局变量, 限制对象的作用域, 变为仅在本文件中使用
(3) static修饰成员变量, 为静态数据成员, 属于这个类的,是这个类的所有对象共享的
(4) static修饰成员函数, 为静态成员函数, 没有this指针, 可以通过类名直接调用