#include <iostream>

using namespace std;
/*
继承与派生,它们是一个概念,只是角度不同
B类继承A类,那么A类的功能B类都有,同时B类可以在A类的基础上扩展更多功能
以下People为A类,Student为B类称为A派生B,B继承A
叫法不同又称A、B为基类与派生类或父类与子类

一般语法为
class 派声明:[继承方式] 基类名
{
	派生类新添的成员
};
继承方式:public(公有的)、pravate(私有的)、protected(受保护的),如果不写默认为private
*/
//基类
class People
{
public:
	void SetName(char *name);
	void SetAge(int age);
	char *GetName(void);
	int GetAge(void);
private:
	char *m_name;
	int m_age;
};
void People::SetName(char *name) { m_name = name; }
void People::SetAge(int age) { m_age = age; }
char *People::GetName(void) { return m_name; }
int People::GetAge(void) { return m_age; }
//派生类
class Student :public People
{
public:
	void SetScore(float score);
	float GetScore();
private:
	float m_score;
};
void Student::SetScore(float score) { m_score = score; }
float Student::GetScore(void) { return m_score; }
void ClassFun(void)
{
	Student stu;
	stu.SetName("小明");
	stu.SetAge(15);
	stu.SetScore(92.5f);
	cout << stu.GetName() << "的年龄是: " << stu.GetAge() << ",成绩是:" << stu.GetScore() << endl;
}
/*
pubilc、private、protected除了修饰类的成员,还可以修饰指定的继承方式
访问权限优先级权限由高到低依次为 public > protected > private

protected成员和private成员类似,也不能通过对象访问
基类中protected成员可以在派生类中使用,而基类中private成员不能在派生类中使用
三种继承方式
1、public继承方式
	基类中所有 public 成员在派生类中为 public 属性;
	基类中所有 protected 成员在派生类中为 protected 属性;
	基类中所有 private 成员在派生类中不能使用。
2、protected继承方式
	基类中的所有 public 成员在派生类中为 protected 属性;
	基类中的所有 protected 成员在派生类中为 protected 属性;
	基类中的所有 private 成员在派生类中不能使用。
3、private继承方式
	基类中的所有 public 成员在派生类中均为 private 属性;
	基类中的所有 protected 成员在派生类中均为 private 属性;
	基类中的所有 private 成员在派生类中不能使用。
对比可看出
1、基类成员在派生类中的访问权限不得高于继承方式中指定的权限。
	也就是在继承方式中的 public、protected、private 是用来指明基类成员在派生类中的最高访问权限的。
2、不管继承方式如何private成员在派生类中始终不能使用
3、如果希望成员不向外暴露,并且在派生类中可以使用,那么就定义成protected
注:
	这里说的是基类的 private 成员不能在派生类中使用,并没有说基类的 private 成员不能被继承。
实际上,基类的 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,
导致无法使用罢了。private 成员的这种特性,能够很好的对派生类隐藏基类的实现,以体现面向对象的封装性。

在派生类中访问基类 private 成员的唯一方法就是借助基类的非 private 成员函数,
如果基类没有非 private 成员函数,那么该成员在派生类中将无法访问。
*/
class People2
{
public:
	void SetName(char *name);
	void SetAge(int age);
	void Sethobby(char *hobby);
	char *GetHobby(void);
protected:
	char *m_name;
	int m_age;
private:
	char *m_hobby;
};
void People2::SetName(char *name) { m_name = name; }
void People2::SetAge(int age) { m_age = age; }
void People2::Sethobby(char *hobby) { m_hobby = hobby; }
char *People2::GetHobby(void) { return m_hobby; }
//派生类Student2
class Student2 :public People2
{
public:
	void SetScore(float score);
protected:
	float m_score;
};
void Student2::SetScore(float score) { m_score = score; }
//派生类Pupil
class Pupil :public Student2
{
public:
	void SetRanking(int ranking);
	void Display(void);
private:
	int m_ranking;
};
void Pupil::SetRanking(int ranking) { m_ranking = ranking; }
void Pupil::Display()
{
	cout << m_name << "的年龄是" << m_age << ",成绩是" << m_score << ",排名是" << m_ranking << ",TA喜欢" << GetHobby() << "." << endl;
}
void ClassFun2(void)
{
	Pupil pup;
	pup.SetName("小明");
	pup.SetAge(15);
	pup.SetScore(92.5f);
	pup.SetRanking(4);
	pup.Sethobby("跑步");
	pup.Display();
}
/*
可以使用using关键字改变访问权限,将 public改为private,protected 改为 public
注:
	using 只能改变基类中 public 和 protected 成员的访问权限,不能改变 private 成员的访问权限,
	因为基类中 private 成员在派生类中是不可见的,根本不能使用,所以基类中的 private 成员在派生类中无论如何都不能访问。
*/
class People3
{
public:
	void show();
protected:
	char *m_name;
	int m_age;
};
void People3::show()
{
	cout << m_name << "的年龄是" << m_age << endl;
}
class Student3 :public People3
{
public:
	void leaening(void);
public:
	using People3::m_name;//将protected改为public
	using People3::m_age;
	float m_score;
private:
	using People3::show;//将public改为private
};
void Student3::leaening(void)
{
	cout << m_name << "今年" << m_age << "岁了,成绩是" << m_score << "分" << endl;
}
void ClassFun3(void)
{
	Student3 stu;
	stu.m_name = "小明";
	stu.m_age = 16;
	stu.m_score = 99.8f;
	//stu.show();//降低权限
	stu.leaening();
}


int main(void)
{
	ClassFun3();
	system("pause");
	return 0;
}