一、类的继承与派生的概念
①概念
保持已有类的特性而构造新类的过程称为继承。在已有类的基础上新增自己的特性而产生新类的过程称为派生。
被继承的已有类称为基类(或父类)。派生出的新类称为派生类。
派生类是基类的具体化,而基类则是派生类的抽象。
②目的
继承的目的:实现代码重用。
派生的目的:当新的问题出现,原有程序无法解决或不能完全解决时,需要对原有程序进行改造。
③派生类的声明
声明一个派生类的一般格式为:
class 派生类名:[继承方式]基类名{
派生类新增的数据成员和成员函数
};

class Person{    //声明一个基类 
	public:
		Person(string name1,string id_number1,int age1);
		~Person();
		void show();  //在基类中定义一个成员函数show()
	private:
		string name;  //姓名 
		string id_number;  //身份证号 
		int age;      //年龄 
}; 
class Student:public Person{    //声明一个公有派生类 
	public:
		Student(string name1,string id_number1,int age1,int credit1);
		~Student();
		void show();   //重新定义一个成员函数show() 
	private:
		int credit;    //学分 
};

在“class Student:”后,跟着关键字public和类名Person,这就意味着类Student继承了类Person。其中,类Person是基类,类Student是派生类。关键字public指出基类Person中的成员在派生类Student中的继承方式。基类名前面有public的继承称为公有继承。如果不显式地给出继承方式关键字,系统默认为私有继承。
从已有类派生出新类时,可以在派生类内完成以下几种功能:
1)可以增加新的数据成员
2)可以增加新的成员函数
3)可以对基类的成员进行重新定义
4)可以改变基类成员在派生类中的访问属性

④代码演示

#include<iostream>
#include<string>
using namespace std;
class Person{    //声明一个基类 
	public:
		Person(string name1,string id_number1,int age1);
		~Person();
		void show();  //在基类中定义一个成员函数 
	private:
		string name;  //姓名 
		string id_number;  //身份证号 
		int age;      //年龄 
}; 
Person::Person(string name1,string id_number1,int age1)
{
	name=name1;
	id_number=id_number1;
	age=age1;
}
Person::~Person()
{
}
void Person::show()
{
	cout<<"\n姓名:"<<name;
	cout<<"\n身份证号:"<<id_number;
	cout<<"\n年龄:"<<age;
}
class Student:public Person{    //声明一个公有派生类 
	public:
		Student(string name1,string id_number1,int age1,int credit1);
		~Student();
		void show();   //重新定义一个成员函数show() 
	private:
		int credit;    //学分 
};
Student::Student(string name1,string id_number1,int age1,int credit1):Person(name1,id_number1,age1)
//定义派生类的构造函数时带上基类的构造函数 
{
	credit=credit1;
}
Student::~Student()
{}
void Student::show()
{
	Person::show();   //调用基类的成员函数show() 
	cout<<"\n学分:"<<credit<<endl;
}
int main()
{
	Student stu1("黎明","110105**********63",19,166);
	stu1.show();   //调用的是派生类中的show() 
	return 0;
}

结果如图所示

java 基类类型 获取派生类类型 java基类和派生类的定义_成员函数


二、基类成员在派生类中的访问属性

派生类可以继承基类中除了构造函数与析构函数之外的成员,但是这些成员的访问属性在派生过程中是可以调整的。从基类继承来的成员在派生类中的访问属性是由继承方式控制的。

①基类中的私有成员。

无论哪种继承方式,基类中的私有成员都不允许派生类继承,即在派生类中是不可直接访问的。

②基类中的公有成员。

公有继承时,基类中的所有公有成员在派生类中仍是以公有成员的身份出现的。

私有继承时,基类中的所有公有成员在派生类中仍是以私有成员的身份出现的。

保护继承时,基类中的所有公有成员在派生类中仍是以保护成员的身份出现的。

③基类中的保护成员。

公有继承时,基类中的所有公有成员在派生类中仍是以保护成员的身份出现的。

私有继承时,基类中的所有公有成员在派生类中仍是以私有成员的身份出现的。

保护继承时,基类中的所有公有成员在派生类中仍是以保护成员的身份出现的。

三、派生类对基类成员的访问规则

①派生类对基类成员的访问形式主要有两种:

1)内部访问,由派生类中新增的成员函数对基类继承来的成员的访问

2)对象访问,在派生类外部,通过派生类的对象对从基类继承来的成员的访问。

②私有继承的访问规则

java 基类类型 获取派生类类型 java基类和派生类的定义_java 基类类型 获取派生类类型_02

#include<iostream>
#include<string>
using namespace std;
class Person{   //声明基类Person 
	public:
		Person(int age1)
		{
		    age=age1;
		}
		void setage(int age1)
		{
			age=age1;
		}
		void show();   //在基类中定义成员函数show() 
	private:
		int age;
}; 
void Person::show()
{
	cout<<"年龄:"<<age<<endl;
}
class Student:private Person{  //声明私有派生类Student 
	public:
		Student(int age1,int credit1);
		void setage_cre(int a1,int c1)
		{
			setage(a1);//基类的setage()函数在派生类中为私有成员,派生类成员函数可以直接访问 
			credit=c1;//成员函数可以访问本类中的私有成员 
		} 
		void show();
	private:
	     int credit; 
};
Student::Student(int age1,int credit1):Person(age1) //定义派生类构造函数时,要加上基类的构造函数 
{
	credit=credit1;
}
void Student::show()
{
	Person::show();  //调用基类的show()显示年龄 
	cout<<"学分:"<<credit<<endl; 
}
int main()
{
	Student stu1(19,166);
	stu1.setage_cre(20,168);//setage_cre在派生类中为公有成员,派生类对象能直接访问 
	stu1.show(); //调用的是派生类中的成员函数公有成员show()派生类对象能访问 
	return 0;
}

③公有继承的访问规则

java 基类类型 获取派生类类型 java基类和派生类的定义_java 基类类型 获取派生类类型_03


④保护继承的访问规则

同私有继承一样。

三、派生类的构造和析构函数

①调用顺序

当创建派生类对象时,首先调用的是基类的构造函数,然后再调用派生类的构造函数;当撤销派生类对象时,先调用的则是派生类的析构函数,随后再调用基类的析构函数。

#include<iostream>
using namespace std;
class B{
	public:
		B()
		{cout<<"B类对象构造中"<<endl;}
		~B()
		{cout<<"析构B类对象"<<endl; } 
}; 
class D:public B{
	public:
		D()
		{cout<<"D类对象构造中"<<endl;}
		~D()
		{cout<<"析构D类对象"<<endl; } 
};
int main()
{
	D OP;
	return 0; 
}

结果如图所示

java 基类类型 获取派生类类型 java基类和派生类的定义_java 基类类型 获取派生类类型_04


从运行结果可以看出:构造函数的调用严格地按照先调用基类的构造函数,后调用派生类的构造函数的顺序执行。析构函数与其调用顺序相反。

②当基类含有带参数的构造函数时,派生类的构造方法

当基类的构造函数没有参数,或没有显式定义构造函数时,派生类可以不向基类传递参数,甚至可以不定义构造函数(如上①代码所示)。

当基类含有带参数的构造函数时,派生类必须定义构造函数,以提供把参数传递给基类构造函数的途径。

派生类构造函数的一般格式为:

派生类名(参数总表):基类名(参数表)

{派生类新增数据成员的初始化语句}

#include<iostream>
using namespace std;
class B{     //声明基类B 
	public:
	B(int n)  //声明构造函数 
	{
		cout<<"B类对象构造中"<<endl;
		i=n; 
	}
	~B()  //声明析构函数 
	{
		cout<<"析构B类对象"<<endl; 
	}
	void dispi()
	{
		cout<<i<<endl;
	}
    private:
    	int i;
}; 
class D:public B{  //声明基类B的共有派生类D 
	public:
		D(int n,int m):B(m)  //定义派生类构造函数时缀上要调用的基类构造函数以及参数 
		{
         cout<<"D类对象构造中"<<endl;
		 j=n; 
		}
	    ~D()   //派生类的析构函数 
	    {
	    	cout<<"析构D类对象"<<endl;
		}
			void dispi()
	{
		cout<<j<<endl;
	}
    private:
    	int j;
};
int main()
{
	D obj(50,60);
	obj.dispi();
	obj.dispi();
	return 0;
}

结果如图所示

java 基类类型 获取派生类类型 java基类和派生类的定义_java 基类类型 获取派生类类型_05