类的继承与派生

继承与派生

1、继承与派生的定义
继承:保持原有类的特性而构建新类的过程
派生:在已有类的基础上新增自己的特性而产生新类的过程。
(其中,被继承的已有类称为基类,派生出来的新类称为派生类)

2、继承与派生的目的
继承:实现代码重用
派生:当新的问题出现时,原有程序无法解决或不能完全解决时,需要对原有程序进行改造

3、派生类的声明
class 派生类名:继承方式 基类名
{
……
}

4、三种继承方式
A.公有继承
B.私有继承
C.保护继承
(不同继承方式的区别主要体现在:
——派生类成员对基类成员的访问权限
——派生类对象对基类成员的访问权限)

A.公有继承(public)
&&基类的public和protected成员的访问属性在派生类中保持不变,但基类中的private成员不可直接访问
&&派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员
&&通过派生类的对象只能访问基类的public成员

//公有继承实例
//派生类访问公有继承的基类成员
#include<iostream>
#include<string>
using namespace std;

class Student
{
private:
	int num;
	string name;
	string sex;
public:
	void get_value()//声明一个输入函数
	{
		cin>>num>>name>>sex;
	}
	void display()//声明一个输出函数
	{
		cout<<"num: "<<num<<endl;
	    cout<<"name: "<<name<<endl;
	    cout<<"sex: "<<sex<<endl;
	}
};

	class Student1:public Student//公有继承
	{
	private:
		int age;
		string addr;
	public:
		void get_value_1()//声明一个输入函数
		{
			get_value();//通过基类的公有成员函数get_value()访问基类的私有成员
			cin>>age>>addr;
		}
		void display_1()//声明一个输出函数
		{
			display();//通过基类的公有成员函数display()访问基类的私有成员
			cout<<"age:"<<age<<endl;
			cout<<"address:"<<addr<<endl;
		}
	};

		/*由于基类的私有成员对派生类说是不能访问的,所以派生类的
		成员函数display_1不能直接访问基类的私有成员。只能通过基类
		的公有成员函数访问基类的私有成员。*/

	int main()
	 {
		Student1 stud1;
		stud1.get_value_1();
		stud1.display_1();
		return 0;
	} 

B.私有继承(private)
&&基类的public和protected成员都已private身份出现在派生类中(降级),但基类中的private成员不可直接访问
&&派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员;在派生类的外部,派生类的对象无法访问基类的全部成员
&&通过派生类的对象不能直接访问基类的任何成员(全部基类成员在派生类中都成为了私有成员,无法进一步派生。私有继承方式一般很少使用)

//私有继承实例
//与上述公有继承相似,只需做如下变化,其他相同部分省略
class Student1:private Student//私有继承

C.保护继承(protexted)
&&基类的public和protected成员都已protected身份出现在派生类中(降级),但是基类的private成员不可直接访问(但保护继承可以进一步派生,而私有继承则不可以)
&&派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员
&&通过派生类的对象不能直接访问基类的任何成员

5、类型兼容规则
A派生类的指针可以隐含转换为基类的指针.
B派生类的对象可以隐含转换为基类对象
C派生类对象可以初始化基类的引用

#include <iostream>
using namespace std;
class B0	//  基类B0声明
{ public:      //  公有成员函数

	void display(){cout<<"B0::display()"<<endl;}	
};

class B1: public B0	
{ public:
	void display(){cout<<"B1::display()"<<endl; }
};
class D1: public B1	
{  public:
	void display(){cout<<"D1::display()"<<endl;}	
};
void fun(B0 *ptr)	
{	
	ptr->display();	//"对象指针->成员名" 
}

int  main()	//主函数
{	B0 b0;	//声明B0类对象
	B1 b1;	//声明B1类对象
	D1 d1;	//声明D1类对象
	B0 *p;	//声明B0类指针
	p=&b0;	//B0类指针指向B0类对象
	fun(p);
	p=&b1;	//B0类指针指向B1类对象
	fun(p);
	p=&d1;	//B0类指针指向D1类对象
	fun(p);
	return 0;
}
运行结果为:B0::display()
		   B0::display()
		   B0::display()

6、派生类的构造函数
声明方法:
派生类名::派生类名(基类所需的形参,本类成员所需的形参):基类名(参数表)
{
本类成员初始化赋值语句;
};
Tips:
&&基类的构造函数不被继承,派生类中需要声明自己的构造函数,派生类的构造函数需要给基类的构造函数传递参数
&&定义构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化可自动调用基类构造函数完成

//在建立一个对象时,执行构造函数的顺序是:①派生类构造函数先调用基类构造函数;②再执行派生类构造函数本身(即派生类构造函数的函数体),用派生类构造函数的形参做基类构造函数的实参
#include<iostream>
#include <string>
using namespace std;	
class Student                              //声明基类
	{
	public:                                  
	   Student(int n,string nam,char s)   //基类构造函数
	    {
		   num=n;
		   name=nam;
		   sex=s; 
	   }
	   ~Student( ) { }                  //基类析构函数(内容为空)
	 protected:                               
	    int num;
	    string name;
	    char sex ;                            
	};

class Student1: public Student  //  声明公用派生类 
 {  
	public:
		Student1(int n,string nam,char s,int a,char ad[ ] ): Student (n,nam,s)     //   派生类构造函数
		{ 
			age=a;       //  对派生类新增的数据成员初始化
			addr=ad;
	    }
		void show( )
		{
			cout<<"num: "<<num<<endl;
			cout<<"name: "<<name<<endl;
			cout<<"sex: "<<sex<<endl;
			cout<<"age: "<<age<<endl;
			cout<<"address: "<<addr<<endl;
		}

	 private:                 //  派生类的私有部分
	   int age;                          
	   string addr;                
};

int main( )
	 {
		Student1 stud1(10010,"Wang-li",'f',19,"115 Beijing Road,Shanghai");
	    Student1 stud2(10011,"Zhang-fun",'m',21,"213 Shanghai Road,Beijing");
	    stud1.show( );            // 输出第一个学生的数据
	    stud2.show( );            // 输出第二个学生的数据
	    return 0;
	}

7、同名隐藏规则
&&若未强行指明,则通过派生类对象使用的是派生类的同名成员。(基类中的同名成员函数会被隐藏)
&&若要通过派生类对象访问基类中被隐藏的同名成员,应该使用基类名限定

8、二义性的问题
产生:当派生类从多个基类派生,而这些基类有从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性。
解决方法:
A.用类名来限定 eg.c1.A::f()或c1.b::f()
B.同名隐藏,即在派生类中声明一个同名成员函数
C.虚基类(最标准的方法)
( 虚基类的声明
class 派生类名:virtual 继承方式 基类名)
在第一级继承时,就要将共同基类设置为虚基类
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值