C++ 类的封装


  类是 C++ 相比 C 的一个非常重要的特性。


#include <iostream>
using namespace std;

class Testd {//用class声明类默认private,用struct声明默认public
/*
类本身是一个模板而不是对象,类中变量只能声明,初始化依赖构造函数,也不能有声明以外的语句
*/
public://外部可以访问
	int a;
	Testd() {//无参构造函数
		a = 1;//隐式的this指针指向对象,等于this->a = 1;
		b = new int;
		*b = 0;
		cout << b << endl;
		//cout << "无参" << endl;
	}
	/*
    this是一个隐式声明的指向调用成员函数的成员的指针
	this指针用途:返回对象本身指针,函数形参和成员变量同名时区分变量
	*/
	Testd(int c) {//有参构造函数
		a = c;
		b = new int;
		*b = 0;
		cout << b << endl;
		//cout << "有参" << endl;
	}
	Testd(const Testd& p) {//拷贝构造函数
		a = p.a;
		b = new int(*p.b);
		f = p.f;
		cout << b << endl;
		//cout << "拷贝" << endl;
	}
	void read() {
		if (!this) return;
        //C++ 允许对一个空的空对象使用成员函数,此处用来增强鲁棒性
		cout << a << endl;
		cout << *b << endl;
		cout << b << endl;
		//cout << "读取" << endl;
	}
	void set(int e, int a) {
		this->a = a;//使用this指针来解决重名问题
		*b = e;
		cout << b << endl;
		//cout << "设置" << endl;
	}
	~Testd() {//析构函数
		cout << b << endl;
		if (b) {//主动释放内存防止泄露
			delete b;
			b = 0;
		}
		//cout << "析构" << endl;
	}
	Testd& add(Testd& p) {//传入一个对象,并返回调用该函数的对象
		this->a += p.a;
		return *this;
	}
	static void set2() {//静态成员函数只能访问静态成员,静态成员不属于对象本身,无this指针
		f = 0;
	}
private://私有,外部函数不可以访问
	int* b;//C++先分析变量声明再分析成员函数,所以成员函数可以在变量声明之前
	static int f;//所有对象共享静态变量,不属于任何一个类
};
int Testd::f = 0;//静态成员必须在类外初始化



class Tes2 {
	friend class Testd;//友元类声明,让Testd类的成员函数可以访问Tes2类的私有成员
	friend void Testd::set2();//友元成员函数声明
	int a;
	mutable int b;//使const方法也能修改的变量加mutable
	friend void Tes2_read(Tes2& y);//将全局函数声明为友元函数以访问类的私有成员变量
public:
	void Tes3() const {//const方法会在这个对象上加const
		cout << a << endl;
		cout << b << endl;
		b++;
	}
	Tes2() :a(1), b(1) {//初始化列表
	}
};
/*初始化列表
作用:对于类成员能减少一次默认构造函数,直接使用拷贝构造函数
必须使用初始化列表:
1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
3. 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化
*/
/*友元类和友元函数
1.友元关系不可以继承,但对已有的方法来说访问权限不改变。
2.如果改写基类的方法则访问权限改变
3.友元关系不具有传递性:若类B是类A的友元,类C是B的友元,类C不一定是类A的友元。
*/

void Tes2_read(Tes2& y) {//Tes2的友元函数,不属于类,无this指针
	y.a = 2;
}

int main() {
	Testd z;
	z.read();
	z.set(5, 6);
	z.read();
	z.a = 4;
	z.read();
	Testd v(z);//拷贝构造函数
	Testd n(10);//有参构造函数
	Testd m = n;//拷贝构造函数
	Testd x = 10;//有参构造函数
	Testd::set2();//静态成员函数无this指针,可以直接在其他函数中调用
	Testd l;
	l.add(z).add(z);//add函数返回成员的引用,所以第二次add传入了l和f
	const Tes2 m_f;//const对象
	m_f.Tes3();//const对象只能调用const函数
	Tes2 as;
	Tes2_read(as);//Tes2的友元函数调用
	return 0;
}