一文详解类的静态成员

文章详细解释了C++中静态成员的概念,包括静态数据成员、静态成员函数以及它们在类设计中的作用。讨论了静态数据成员的共享性质和访问方式,以及静态成员函数与非静态成员函数的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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指针, 可以通过类名直接调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值