一.const成员:让对象更安全

1.const关键字的作用

C++中const用来表示“常量”的意思,用来修饰变量,表示这个变量的值不可被修改。

2.const修饰普通变量

const int a=10;

此时表示“a”是常量,不可修改。
另外,const修饰的变量必须在定义时初始化,否则就会报错。

例如:
在这里插入图片描述

3.const修饰类成员变量

const修饰的类成员变量必须在初始化列表初始化,并且不能在构造函数体内赋值。
例如如下两种写法都是错的:
在这里插入图片描述
在这里插入图片描述

4.const修饰类成员函数

语法:
返回值 函数名(参数)const
{
...函数体
}

作用:const修饰的成员函数保证不会修改函数内对象的成员变量。

例如:
在这里插入图片描述
如果想让成员变量可以被const成员函数修改,可以使用“mutable”修饰变量。
例如:
在这里插入图片描述

使用:const对象只能调用const成员函数,非const对象可以调用任意成员函数。
例如:

class Test
{
public:
	Test(int x)
		:a(x)
	{}
	void Print1()
	{
		cout << "a:" << a << endl;
	}
	void Print2() const
	{
		cout << "a:" << a << endl;
	}

private:
	int a;
};

int main()
{
	Test t1(10);
	const Test t2(20);

	t1.Print1();
	t1.Print2();

	t2.Print1();//错误,const对象只能调用const成员函数
	t2.Print2();


	return 0;
}

5.const成员函数和非const成员函数重载

同名const成员函数和非const成员函数可以重载,实现const对象和非const对象的不同行为。
例如:

class Test
{
public:
	Test(int x)
		:a(x)
	{
	}
	void Print()
	{
		cout<<"普通成员函数 " << "a:" << a << endl;
	}
	void Print() const
	{
		cout << "const成员函数 " << "a:" << a << endl;
	}

private:
	int a;
};

int main()
{
	Test t1(10);
	const Test t2(20);

	t1.Print();	//调用普通成员函数

	t2.Print();	//调用const成员函数

	return 0;
}

代码运行结果为:
在这里插入图片描述

二.static静态成员:类级共享与生命周期管理

1.什么是static静态成员

在C++中,“static”可以修饰类中的成员变量和成员函数,被“static”修饰的成员就被称作“静态成员变量”,“静态成员函数”。

2.static静态成员作用

在类中,被static修饰的成员表示该成员脱离对象实例,成为类本身的属性

3.静态成员变量

被“static”修饰的成员变量就叫静态成员变量。

  • 特性:
    ① 所有对象共享同一份静态成员变量。
    ② 必须在类外定义并初始化(除非是const static整型),因为它属于整个类,存储在静态区。
    ③ 不占用对象的内存空间。
  • 示例:
    比如我们定义了一个学生类,想统计创建了多少个学生类对象,如果使用普通成员变量,比如
class Student
{
public:
	Student()
	{
		_count++;
	}
private:
	int _count;
};

这种是错误的写法,因为这样写每个学生对象都会创建一个自己的_count变量,无法统计总数。
此时就可以使用“static”关键字。

class Student
{
public:
	Student()
	{
		_count++;
	}
	static  int _count;//只是声明
};

int Student::_count = 0;//类外定义并初始化

int main()
{
	Student s1;
	Student s2;
	Student s3;

	cout << "学生类对象个数为:" << Student::_count;
	return 0;
}

代码运行结果为:
在这里插入图片描述

4.静态成员函数

被“static”修饰的成员函数就叫静态成员函数。

  • 特性:
    ① 无this指针,所以不能访问非静态成员变量/函数。
    ② 可通过类名或对象名调用(推荐类名::函数名)
    ③ 静态成员函数不能同时被const修饰,因为const修饰本质是修饰this指针,但静态成员函数不含this指针。
  • 示例:
class Student
{
public:
	Student()
	{
		_count++;
	}

	static void PrintCount()
	{
		cout << "学生类对象个数为:" << _count << endl;
	}
private:
	static  int _count;//只是声明
};

int Student::_count = 0;//类外定义并初始化

int main()
{
	Student s1;
	Student s2;
	Student s3;

	Student::PrintCount();//通过类名::函数名调用

	return 0;
}

代码运行结果为:
在这里插入图片描述

三.友元:突破封装的特权机制

1.为什么需要友元

C++中类的封装限制了私有成员不能在类外直接访问。
例如:

class Student
{
public:
	Student(int age)
		:_age(age)
	{}

private:
	int _age;
};

如果在类外访问,是错误的
Student s(18);
s.age = 19;//错误,私有成员类外不可直接访问

但有些情况下,类外需要访问类的私有成员,此时就需要使用友元突破封装的限制。

2.友元的概念

友元可以分为友元函数和友元类,友元可以访问当前类的私有成员和保护成员。

3.友元函数

  • 定义:
    友元函数不是类的成员函数,它是在类外定义的普通函数,但需要在类内使用“friend”声明。

  • 特点:
    ① 可以访问类的私有成员和保护成员。
    ② 没有this指针(因为不是类的成员)。
    ③ 友元函数声明可以放在类的任何地方(无论放在 private、protected 还是 public,效果都一样)。
    ④ 一个函数可以是多个类的友元函数。

例如定义一个学生类和打印学生信息的友元函数:

class Student
{
	friend void Print(const Student& s);//友元函数声明
public:
	Student(string name,int age)
		:_name(name),
		_age(age)
	{}

private:
	string _name;
	int _age;
};

//类外定义友元函数
void Print(const Student& s)//打印学生信息
{
	cout << "学生信息为:" << s._name << " " << s._age << "岁" << endl;
}
int main()
{
	Student s("张三",18);
	Print(s);

	return 0;
}

代码运行结果为:
在这里插入图片描述

4.友元类

  • 定义:
    一个类被声明另一个类用“friend”关键字声明,那么这个类就是另一个类的友元类。
  • 特性:
    ① 友元类的所有成员函数都可以访问另一个类的私有成员和保护成员。
    ② 友元类的友元关系是单向的(A是B的友元类,B不一定是A的友元类)。
    ③ 友元关系不能继承(父类的友元不一定是子类的友元)。
    ④ 友元关系不能传递(某个类的友元的友元不一定是它的友元,比如你朋友的朋友不一定是你的朋友)。
    示例代码:
class Student
{
	friend class Teacher;
public:
	Student(string name,int age)
		:_name(name),
		_age(age)
	{}

private:
	string _name;
	int _age;
};

class Teacher
{
public:
	void PrintStudent(const class Student& s)
	{
		cout << "学生信息为:" << s._name << " " << s._age << "岁" << endl;
	}
};

int main()
{
	Student s("张三",18);
	Teacher t;
	
	t.PrintStudent(s);

	return 0;
}

代码运行结果为:
在这里插入图片描述
感谢阅读!在这里插入图片描述

更多推荐