静态成员

静态成员可以在类的所有对象之间共享数据,也可以提供不依赖类的对象的操作。静态成员是类的整个生命周期中存在的。
在 c++类中声明成员是,加上 static 关键字
静态成员分为静态数据成员和静态函数成员两种

声明:在类中声明 static int count;
定义:在类外定义 int Ball:: count = 0;
注意:不管静态成员是什么访问属性,都是在类外初始化

静态成员属于类,不属于对象,所有对象访问静态成员都是访问同一个位置,所有对象共享
普通成员属于对象,是这个类对象自己的

访问方式:
成员变量:

  1. ‘对象. count’
  2. ‘类名::count’
    成员函数访问:通过类名调用静态成员函数,如果是普通的成员函数可以调用静态变量
    非静态变量没办法在静态函数中调用,因为静态函数的调用没有 this 指针指向特定的对象,而非静态变量是特定对象的成员

静态数据成员特点:

  1. 只会被定义一次,所有对象共享这个数据
  2. 不管是什么访问属性类中声明,类外初始化
  3. 如果是公有访问属性,那么可以类外直接<类名::静态数据成员>访问
  4. 构造函数里面可以重新赋值

生命周期:从程序启动到程序结束

使用场景:

  1. 共享数据:静态成员可以被所有对象共享,比如用来实现访问相同的计数器变量
  2. 全局数据:静态成员可以被视为类的全局变量,不用创建类对象就可以访问到,因为它的存在依赖类,只要类存在它就已经出来了
  3. 类方法:静态成员函数不依赖于类的实例,因此他们可以用于执行与特定对象无关的操作。静态成员函数通常用于执行与类相关的全局任务与操作

代码

#include <iostream>
 
class Ball{
public:
	int id;
	static int count;
	Ball(){//第一个构造函数
		count++;
	}
	Ball(int id){//第二个构造函数
		this->id = id;
		count++;
	}
	~Ball(){
		count--;
	}
};
int Ball::count = 0;//静态成员变量初始化
 
int main(){
    Ball a1(1);
    Ball a2(2);
    Ball a3(3);
    std::cout<<a1.count<<a2.count<<a3.count<<std::endl;//三个一样
    std::cout<<a1.id<<a2.id<<a3.id<<std::endl;//三个不一样
    return 0;
}

单例设计模式

如果在同一个源文件夹下好几个源文件的不同函数想调用同一个变量用 extern,不同模块访问该变量都是同一个变量

c 中单例变量

//源文件A:
include <iostream>
 
int a = 0;
int main(){
	a = 10;
	fun();
	std::cout << a << endl;//输出:20
}
 
//源文件B:
extern int a;//说明只有一个a被定义让程序去找,用同一个a
void fun{
	a = 20;
}

c++中单例类:

  1. 将构造函数放在 private 下,避免外面主动调用构造函数创建新的对象
  2. Net 类型的静态成员
  3. 静态函数中获取到这个对象
#include <iostream>
 
class Net {
private:
	Net(){}//构造函数
	static Net* net;//声明一个静态成员	
public:
	static void getNet(){//静态函数调用静态变量
		if (net == nullptr){
			net = new Net();//如果是空就new一个Net类空间给它
		}
		return net;
	}
}
Net* Net::net = nullptr;//nullptr就是空。此格式类似第本文件第54行

实际上 class 一般单独开一个 cpp 文件,而不是跟 main 放一起的

常量成员

常量成员指都是 C++类中声明对象成员时可以加上 const 关键字,使之不能修改,即只读

必须要初始化,初始化后无法再修改

初始化:

  • 直接赋值 const std:: string filename = “a.txt”
  • 初始化列表 filename(“b.txt”)

常量成员函数

常量对象无法调用非常量成员函数

int main() {
    MyClass obj1;          // 非常量对象
    const MyClass obj2;    // 常量对象
 
    obj1.getValue();       // ✅ 可以调用(非常量对象可以调用const函数)
    obj1.setValue(5);      // ✅ 可以调用
 
    obj2.getValue();       // ✅ 可以调用(常量对象可以调用const函数)
    obj2.setValue(5);      // ❌ 编译错误!常量对象不能调用非const函数
}
 

常量成员函数不会修改任何成员变量

代码

class Log {
private:
	const std::string filename = "a.txt"
public://当两个初始化方法都有时,初始化列表优先级更高
	Log(const char* name):filename(name){
		
	}
	
	std::string getFilname(){
		return filename;
	}
	
	std::string getFilname() const{//const加在后面是因为加前面就修饰返回值而非函数
		return filename;
	}

友元

友元函数只是放个 friend 声明在类里面,不是类的成员函数

友元类跟友元函数类似,一样友元声明 firend class B;

友元是单向的,类 A 声明了类 B 是友元,B 可以用 A 但 A 不可以用 B 的私有成员

class A {
private:
	int a;
	friend void fun();
	friend class B;
};
class B {
public:
	void fun1(){
		A a;
		a.a = 10;//A类的类对象里的成员都可以访问
	}
};
 
void fun(){
	A c;
	c.a = 10;//正常去点是点不出来的,应为a是private的,但是设为友元函数就可以了
}