彻底弄清楚C++ static 静态成员与静态成员函数的原理

参考mooc魏英《C++程序设计》
文字是魏老师的讲解,纯手打,ppt上没有。

为什么会用到静态成员:现在大型应用程序都是由多个程序员所开发的,那么多个程序员就需要使用一个共同都能使用的数据来解决一些问题,采用静态数据成员解决这一问题。

在这里插入图片描述在这里插入图片描述
思考一下现在我们需要统计员工的总人数,能不能在这个员工类中增加一个成员专门用来存放总人数呢?这样做是不好的:1.每个对象都要增加一个这样的成员,对存储空间是一种浪费。对于公司来说,总人数只有一个值,那么每个对象都要增加一个这样的成员,浪费存储空间。2.使用不方便,当总人数改变时,意味着每个对对象里面成员里的值都要改变。

增加静态数据成员解决这一问题:
在这里插入图片描述
其中的static int count是不属于任何一个对象的,也就是所有员工类的对象共享一个count,这个count属于一个类,而不属于任何一个对象,这样就大大减少了存储空间,并且当员工总人数修改后,只需要改一次就行了。
在这里插入图片描述
在这里插入图片描述
注意在类里面只是对这个静态变量进行了一个声明,但是它还不存在,要让它占有存储空间并存放数据,就要在类外对它做一个定义。

其他数据成员为什么不用在类外做定义呢?
当生成对象的时候,这个对象就会被分配存储空间。静态数据成员不属于每个对象,而是属于类,一个类只有一个数据成员,所以需要在类外对其定义并赋初值。

在构造函数里添加了一个count++,则每创建一个Data类的对象,都会调用构造函数,count都会加一,最后统计这个count的值时就能知道创建了多少个这个类的对象。
在这里插入图片描述
在这里插入图片描述
静态成员如果定义为私有成员,同样只有类里面的成员才能使用这个静态成员。如果是公有的在类外就可以直接访问。
在这里插入图片描述
在这里插入图片描述
成员函数也可以是静态的
在这里插入图片描述
在这里插入图片描述
静态数据成员是不用对象进行调用的,直接 类名::静态成员名 就可以被调用。静态成员函数既可以通过 类名::静态函数名 调用也可以通过 对象.静态函数名 调用。
在这里插入图片描述
静态成员函数是专门用来访问静态成员的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
A处为什么不直接输出s_total的值呢?因为s_total是private类型的,类外不能直接访问。只能通过gettotal()这个public类型的函数去调用它。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
B处出错原因:静态成员函数不能调用非静态成员。
在这里插入图片描述
C处非静态成员函数是可以调用静态成员函数的。反之不行。
在这里插入图片描述

在测试时发现静态成员初始化必须在类的.cpp源文件中初始化,否则会报错。
base.h

#pragma once

#include<iostream>
#include<ctime>
#include<windows.h>//在Linux和Mac下要换成 unistd.h 头文件
class Base
{
public:
	Base(int a=0,int b=0);
	Base(const Base &obj);
	~Base();
public:
	int getCount() const { return m_count; }
	time_t getTime() const { return m_time; }
private:
	int m_a;
	int m_b;
	time_t m_time;
public:
	static int m_count;

};

base.cpp

#include "base.h"
Base::Base(int a, int b):m_a(a),m_b(b)
{
	m_count++;
	m_time = time((time_t*)NULL);
}
Base::Base(const Base &obj) {
	this->m_a = obj.m_a;
	this->m_b = obj.m_b;
	this->m_count++;
	this->m_time = time((time_t*)NULL);
}
Base::~Base(){}
int Base::m_count = 0;//静态成员初始化在类的.cpp源文件中初始化

main.cpp

#include "base.h"
using namespace std;
int main() {
	Base obj1(10, 20);
	cout << "obj1:count=" << obj1.getCount() << ",time" << obj1.getTime() << endl;
	Sleep(3000);
	Base obj2 = obj1;
	cout << "obj2:count=" << obj1.getCount() << ",time" << obj2.getTime() << endl;
	system("pause");
	return 0;
}

当静态成员初始化不在类的.cpp源文件中初始化,比如在main.cpp中初始化(int Base::m_count=0)时。会出现如下重定义的错误:
在这里插入图片描述

改成如下:
Base::m_count = 0;
会出现如下错误:
在这里插入图片描述
总之得出结论:静态成员初始化需要在类的.cpp源文件中初始化

### 回答1: 在C++中,静态成员函数是类的成员函数,它不与任何特定的对象相关联,而是被整个类所共享。同样地,静态成员也不依赖于类的任何对象,而是属于类本身。 静态成员函数可以访问和修改静态成员变量。由于静态成员变量存在于整个类中,所以它们的值可以在类的任何成员函数中进行修改,包括静态成员函数。 要在静态成员函数中修改静态成员变量,可以直接使用静态成员变量的名称进行赋值操作。在静态成员函数中,不需要通过对象来访问静态成员变量,而是可以通过类名来直接访问。 例如,假设有一个类Car,其中包含一个静态成员变量totalCars表示创建的汽车总数,以及一个静态成员函数addCar用于增加汽车总数。可以在addCar函数中通过类名Car来访问并修改totalCars的值。代码示例如下: ```c++ #include <iostream> class Car { public: static int totalCars; // 静态成员变量 static void addCar() { totalCars++; // 修改静态成员变量 } }; int Car::totalCars = 0; // 初始化静态成员变量 int main() { Car::addCar(); // 使用静态成员函数修改静态成员变量 std::cout << "Total cars: " << Car::totalCars << std::endl; // 输出修改后的静态成员变量值 return 0; } ``` 以上代码中,首先通过Car::addCar()调用静态成员函数addCar,在addCar函数中通过totalCars++来将totalCars的值增加1。最后在main函数中使用Car::totalCars输出修改后的totalCars值。 ### 回答2: 静态成员函数是属于一个类的函数,它不依赖于类的对象,而是属于整个类的共享函数静态成员函数可以通过类名直接调用,不需要创建类的对象。 静态成员函数可以访问和修改静态成员变量。静态成员变量是属于类的成员变量,不依赖于类的对象而存在,在类的所有对象中共享同一份副本。 在静态成员函数中修改静态成员变量的步骤如下: 1. 首先,在类的定义中声明静态成员变量。 2. 在类的外部定义静态成员变量,为其分配内存空间。 3. 在静态成员函数中使用类名加作用域运算符来访问和修改静态成员变量。 例如,假设有一个名为"ClassA"的类,其中包含一个静态成员变量"static_var"和一个静态成员函数"static_func"。我们可以按照以下步骤修改静态成员变量: 1. 在ClassA类的定义中添加静态成员变量声明:static int static_var; 2. 在类的外部定义静态成员变量:int ClassA::static_var = 0; 3. 在静态成员函数static_func中使用类名加作用域运算符来访问和修改静态成员变量: ``` void ClassA::static_func() { static_var = 10; // 修改静态成员变量static_var为10 } ``` 通过以上步骤,我们可以使用静态成员函数来修改静态成员变量。这样做的好处是,我们不需要创建类的对象就可以直接通过类名调用静态成员函数来修改静态成员变量的值。这种特性使得静态成员函数在一些不需要操作对象而仅仅需要修改静态成员变量的场景中非常有用。 ### 回答3: 静态成员函数是属于整个类而不是类的实例的函数。它可以直接访问和修改静态成员,因为静态成员是属于类的而不是单个对象的。 静态成员函数修改静态成员的过程与访问和修改普通静态成员的过程相同,可以使用类名加上作用域解析运算符(::)来引用和修改静态成员。 以下是一个示例: ```cpp class MyClass { static int staticMember; public: static void changeStaticMember(int value) { staticMember = value; } }; int MyClass::staticMember = 0; // 初始化静态成员 int main() { MyClass::changeStaticMember(10); // 调用静态成员函数来修改静态成员值 return 0; } ``` 在上面的示例中,我们定义了一个名为`MyClass`的类,其中包含一个静态整数静态成员`staticMember`。在`changeStaticMember`静态成员函数中,我们直接使用作用域解析运算符(`::`)来引用和修改`staticMember`的值。在`main`函数中,我们通过调用`MyClass::changeStaticMember(10)`来修改`staticMember`的值为10。 需要注意的是,静态成员函数只能访问和修改静态成员,而不能访问和修改非静态成员或对象的特定属性。因此,在静态成员函数中无法使用`this`指针来引用特定的对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙叙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值