28.【C++ 继承与派生 (详解)】

(一)、什么是继承与派生

(1).继承是自然界一个普遍的重要特性,源于人们对客观世界的认识。(狗和黑狗的特性)一般到特殊的关系.

(2).继承机制,就是在一个已存在的类(父类)的基础上建立一个新的类,这个新的类**(子类)自动拥有已有类的全部成员的一种机制**,进而体现出层次性.(下层是上层的特殊类)

(3).继承是类之间定义的一种重要关系,已有类A的基础上定义类B,类B会自动得到类A的函数成员和数据成员,使得程序员只需在类B定义类A中所没有的新成分就柯完成在类B的定义,
在这种情况下,就称类B继承了类A,类A派生了类B,A是基类(父类),B是派生类(子类),这种机制叫做继承

(二)、为什么要使用继承和派生?

类的继承和派生机制使程序员无需修改已有的类,只需在既有类的基础上,根据问题的实际需要,通过增加部分代码或修改少量代码而得到的新的类(派生类),从而解决了程序代码的重用问题.

(三)、继承方式

公有继承,私有继承,保护继承,

如果缺省:就是声明的时候继承方式是空的,那就默认为是按照私有继承方式继承.

(四)、继承的属性

 (1).继承基类的成员函数和数据成员
 (2).增加新的数据成员和成员函数.
 (3).重载或重新定义继承自基类的成员函数
 (4).改变基类成员在派生类中的访问属性

1.添加新的数据成员和成员函数


#include <iostream>
using namespace std;
class Base    
{
private:
	int x;
public:
	void setX(int i)
	{
		x=i;
	}
	void show()
	{
		cout<<"x="<<x<<endl;
	}
};
class Drevid: public Base  
{
public:
	  void show1()     //添加成员函数
	{
		cout<<"LWT love Lwt"<<endl;
	}
};
int main()
{
	Base b;
	b.setX(10);
	b.show();
	Drevid d;
	d.setX(20);   //  改变成员   
	d.show();	//继承成员							
	d.show1();                           
	return 0;
}

2.覆盖改变成员

#include <iostream>
using namespace std;
class Base                                      //基类
{
private:
	int x;
public:
	void setX(int i)
	{
		x=i;
	}
	void show()
	{
		cout<<"x="<<x<<endl;
	}
};
class Drevid: public Base                
public:
	void show1()
	{
		cout<<"我喜欢!"<<endl;
	}
	void show()                           
	{
		cout<<"喜欢我!"<<endl;
	}
};
int main()
{
	Base b;
	b.setX(10);
	b.show();
	Drevid d;
	d.setX(20);                            
	d.show();	//覆盖							
	d.show1();
	return 0;

(五)、继承方式和派生类的访问权限

(1).公有继承(公私保变公私保)

最常见的继承方式,基类的public成员仍然作为派生类的public成员;基类中的privat成员被隐藏(使得派生类内部也变得不可以直接访问私有成员)。虽然不能够直接访问基类的private成员,但可通过从基类的公有成员访问派生类的对象可以访问基类中的非private成员;

派生类的对象只能访问基类中的public成员

(2).保护继承(公私保全变保)

派生类的内部,基类的公有成员和保护成员均作为派生类的保护成员,派生类的成员可以直接访问它们,而派生类的成员无法访问基类的私有成员。

保护继承时基类中各成员属性均变为protected,并且基类中private成员被隐藏。派生类的成员只能访问基类中的public/protected成员,而不能访问private成员;派生类的对象不能访问基类中的任何的成员

1.本类内部: 可以访问基类的public/private
2.本类的对象: 不能访问基类的任何成员
3.本类的派生类内部: 可以访问基类的public/private
4.本类的派生类对象: 不能访问基类的任何成员

派生类的外部:派生类的成员和派生类的对象均无法访问基类的全部成员

如果基类只进行了一次派生,则保护继承和私有继承的功能完全相同,但保护继承可以进一步派生,而私有继承则不可以.

(3).私有继承:(公私保变私)

基类中的private被隐藏,在派生类的内部,基类的公有成员和保护成员作为派生类的私有成员,派生类的成员可以直接访问基类中(公有和保护),而派生类的对象无法访问基类的任何成员

私有继承之后,全部基类成员在派生类中都成为了私有成员或不可访问的成员,进一步派生后,将再也无法直接访问

派生类对象不能访问基类中的任何的成员函数

(六)各种实列

1.【公有继承下派生类通过公有成员访问私有成员】

#include <iostream>
using namespace std;
class Base                                      
{
private:
	int x;
public:
	void setX(int i)
	{
		x=i;
	}
	void show()
	{
		cout<<"x="<<x<<endl;
	}
	int getX()      //共有返回私有
	{
		return x;
	}
};
class Drevid: public Base                  
{
public:
	void display()
	{
		cout<<"x="<< getX()<<endl;      //访问基类中的私有
	}	
};
int main()
{
	Base b;
	b.setX(10);
	b.show();
	Drevid d;
	d.setX(20);
	d.display();
	return 0;
}

2.【公有继承下派生类通过公有成员访问保护成员】

#include <iostream>
using namespace std;
class Base
{
protected:     //保护
	int x;
public:
	void setX(int i)
	{
		x = i;
	}
	void show()
	{
		cout << "x=" << x << endl;
	}
	int getX()      //共有返回保护
	{
		return x;
	}
};
class Drevid : public Base
{
public:
	void display()
	{
		cout << "x=" << getX() << endl;      //访问基类中的保护
	}
};
int main()
{
	Base b;
	b.setX(10);
	b.show();
	Drevid d;
	d.setX(20);
	d.display();   
	return 0;
}

3.【私有继承下类外不能访问基类的所有成员】

#include <iostream>													
using namespace std;
class Base                                      
{
private:
	int y;
protected:
	int x;
public:
	void setX(int i)
	{
		x=i;
	}
	void show()
	{
		cout<<"x="<<x<<endl;
	}
};
class Drevid: private Base               //私有继承访问                 
{
public:
		void show1()

		{
			cout<<"我的名字:"<<endl;
		}
};
int main()
{
	Base b;
	b.setX(10);							
	b.show();						     
	Drevid d;
//	d.setX(20);   //会报错,因为现在基类的公有成员被私有成员访问,所以...
//	d.show();     //会报错,因为现在基类的公有成员被私有成员访问,所以...                     
	return 0;
}

4.【私有继承下访问基类的私有数据成员】

#include <iostream>													
using namespace std;
class Base
{
private:
	int y;
protected:
	int x;
public:
	void setY()
	{
		cout << "结果为:y=" << 10 << endl;
	}
	void setX(int i)
	{
		x = i;
	}
	void show()
	{
		cout << "x=" << x << endl;
	}
	int getX()
	{
		return x;
	}
};
class Drevid : private Base
{
public:
	void show1()
	{
		setY();                      //会变成私有
	}
};
int main()
{
	Base b;
	b.setX(10);
	b.show();
	Drevid d;
	d.show1();    //派生类可以访问派生类
	return 0;
}

5.【私有继承下进一步派生】


#include <iostream>													
using namespace std;
class Base                                      
{
private:
	int y;
protected:
	int x;
	void setY()
	{
		y=10;
	 }
public:
	void setX(int i)
	{
		x=i;
	}
	void show()
	{
		cout<<"x="<<x<<endl;
	}
	int getX()
	{
		return x;
	}
};
class Drevid: private Base                     
{
public:
	void show1()
	{
		setY();                      //基类中的保护会员变成私有成员
	}	
};
class DDrevid: public Drevid          //用公有继承的方式进一步派生后
{
public:
	void f()
	{
	//	setY();        报错             //进一步派生后,仍然还是私有成员
	}
};
int main()
{
	Base b;
	b.setX(10);
	b.show();
	Drevid d;
//	d.setY();        报错     //这个已经变成派生类的私有成员,在类外不能访问.
	d.show1();   
	DDrevid d1;
	d1.f();           //进一步派生后,仍然无法访问
	return 0;
}

6.【保护继承进一步派生】

#include <iostream>													
using namespace std;
class Base
{
private:
	int y;
protected:
	int x;
	void setY()
	{
		y = 10;
	}
public:
	void setX(int i)
	{
		x = i;
	}
	void show()
	{
		cout << "x=" << x << endl;
	}
	int getX()
	{
		return x;
	}
};
class Drevid : protected Base
{
public:
	void show1()
	{
		setY();                      //基类中的保护成员会变成保护成员
	}
};
class DDrevid : public Drevid
{
public:
	void f()
	{
		setY();                     //进一步派生后,公有继承下仍然是保护成员
	}
};
int main()
{
	Base b;
	b.setX(10);
	b.show();
	Drevid d;
	//	d.setY();         报错    //这个已经变成派生类的保护成员,在类外不能访问.
	d.show1();
	DDrevid d1;
	d1.f();              //可以访问
	return 0;
}

(七)、派生类的构造函数

1.什么是派生类的构造函数:

1.派生类的数据成员既包括从基类继承的数据成员,也包括派生类新增的数据成员,甚至还可能包括派生类内定义的内嵌成员对象.

2.派生类构造函数在对派生类对象进行初始化时需要对基类数据成员,新增数据成员和内嵌对象成员进行初始化.

3.派生类会继承除基类构造函数外的所有基类成员,也就是说,(派生类是不能继承基类的构造函数的!!!)

4.在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须借助派生类的构造函数,调用基类的构造函数,从而结组基类的构造函数,从而借助基类的构造函数,来初始化从基类继承的数据成员.

5.如果派生类拥有对象成员时,派生类的构造函数还拥有对象成员所属类构造函数,来初始化这个对象成员.

2.派生类构造函数的格式(构造函数先基再派,析构函数先派后基)

(2).派生类的构造函数的定义格式:

派生类名::派生类名(): 类名(),内嵌对象成员名1…
{
派生类新增成员的初始化
}

(3).当基类中没有显示定义构造函数时,派生类的构造函数定义可以省略,系统采用默认的构造函数

(4).当基类定义了具有形参的构造函数时,派生类很可能也需要显示定义构造函数,提供将参数传递给基类构造函数的途径,使基类对象在初始化时可以获取相关数据,在某些情况下,派生类构造函数的函数体可能为空,仅起参数产地及调用基类与内嵌对象构造函数的作用

(5).派生类定义构造函数会自动调用基类构造函数

3.实列(派生类构造函数的初始化)

代码展示:

#include <iostream>
using namespace std;
class Inner
{
private:
	int y;
public:
	Inner(int b)
	{
		y=b;
		cout<<"inner的构造函数:"<<y<<endl;
	}
};
class Base
{
protected:
	int x;
public:
	Base(int a)
	{
		x=a;
		cout<<"基类的构造函数:"<<x<<endl;
	}
};
class Derived: public Base
{
private:
	Inner i;
	int z;
public:
	Derived(int a,int b,int c):Base(a),i(b)									//派生类构造函数,有内嵌,加派生类新增
	{
		z=c;
		cout<<"派生类的构造函数:"<<z<<endl;
	}
};
int main()
{
	Base b(100);
	cout<<"*************************************"<<endl;
	Derived d(10,20,30);                                                       //+++++++++++++++
	return 0;
}

在这里插入图片描述
如有不解,随时支持私聊!!!!!

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吉士先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值