c++学习之继承

目录

一,为什么需要继承

二,继承的基本概念

 三,派生类的定义

四,继承中的析构预构造

1,子类中的构造与析构的顺序

2,子类调用成员对象,父类的有参构造

五,子类与父类的同名处理

1.子类和父类 同名成员数据

2.子类和父类 同名成员函数


一,为什么需要继承

目的:提高代码重用,提高i开发效率。例如我们已经拥有了制作某一零件的整套设备,以这套设别为基础之上,通过改造这个设备以实现其他种零件的制作,省去了从新研发等的时间。类比于c++语言中,就是通过实现继承该类并改造,实现其他功能。

二,继承的基本概念

c++最重要的特征是代码重用,通过继承机制可以利用已有的数据类型来定义新的数据类型,新的类不 仅拥有旧类的成员,还拥有新定义的成员。 一个B类继承于A类,或称从类A派生类B。这样的话,类A成 为基类(父类), 类B成为派生类(子类)。

派生类中的成员,包含两大部分: 一类是从基类继承过来 的,一类是自己增加的成员。 从基类继承过过来的表现其共性,而新增的成员体现了其个性。

如图所示:

例如给定一个基类,我们可理解为是一个父亲类,在继承父亲类的某些功能,定义的新类也就是派生类(这里可当作子类),子类除了继承以外的功能,还有自己的一些功能。

 c++学习之继承_第1张图片

 三,派生类的定义

我们通常这样定义子类(派生类),在有基类的前提下,定义子类在类定义的基本方式下,还需在后添加:继承方式  基类名

class 父类{};
class 子类:继承方式 父类名
{
//新增子类数据
};

这里的继承方式就是所谓基类中的public,private ,protected中的类型的成员,一般这里我们是使用公共继承的。

如图以下的三种继承方式:

c++学习之继承_第2张图片

 继承方式决定他们可以继承过来成员在派生类中是什么类型的,故我们可以知道,任何父类都不能将私有类型数据通过继承给予子类。如下:

#include
using namespace std;
//定义基类
class Base
{
private:
	int a;
protected:
	int b;
public:
	int c;
};
//定义派生类
class Son :public Base
{
public:
	void fun()
	{
		cout << b << c << endl;
		//cout<

很显然如果是公有继承过来,b还是保护型的,对于私有的直接是无法继承,所以这里的b是无法访问的。

四,继承中的析构预构造

1,子类中的构造与析构的顺序

对于派生类中的构造与析构的顺序看可用下图展示:

c++学习之继承_第3张图片

 

即构造时:先构造父类,再构造对象中的构造函数,最后才是子类的构造,而析构就是与之相反。

如下:

class Base
{
public:
	Base()
	{
		cout << "父类构造" << endl;
	}
	~Base()
	{
		cout << "父类析构" << endl;
	}
};
class member
{
public:
	member()
	{
		cout << "对象构造" << endl;
	}
	~member()
	{
		cout << "对象析构" << endl;
	}
};
class Son :public Base
{
public:
	member a;
	Son()
	{
		cout << "子类构造" << endl;
	}
	~Son()
	{
		cout << "子类析构" << endl;
	}

};
int main()
{
	Son p;
	return 0;
}

c++学习之继承_第4张图片

 我们可以看到构造与析构的顺序。

2,子类调用成员对象,父类的有参构造

子类实例化对象时会自动调用成员对象、父类的默认构造。

子类实例对象时必须使用初始化列表 调用成员对象、父类的有参构造。(无参构造就不需要)

初始化列表时:父类写类名称 成员对象用对象名。

class Base
{
public:
	Base()
	{
		cout << "父类构造" << endl;
	}
	Base(int a)
	{
		cout << "父类有参构造" << endl;
		x = a;
	}
	~Base()
	{
		cout << "父类析构" << endl;
	}
	int x;
};
class member
{
public:
	member()
	{
		cout << "对象构造" << endl;
	}
	member(int a)
	{
		cout << "对象有参构造" << endl;
		y = a;
	}
	~member()
	{
		cout << "对象析构" << endl;
	}
	int y;
};
class Son :public Base
{
public:
	member a;
	int c;
	Son()
	{
		cout << "子类构造" << endl;
	}
	
	Son(int a, int b, int c) :Base(a), a(b)//初始化列表,基类用基类名显式调用,而对象调用用对象名么人不是类名
	{
		this->c = c;
		cout << "Son有参构造" << endl;
	}
	~Son()
	{
		cout << "子类析构" << endl;
	}

};
int main()
{
	Son p(10,20,30);
	return 0;
}

c++学习之继承_第5张图片

 注意初始化列表中基类与成员的构造调用!!

五,子类与父类的同名处理

我们先给出最实用的方法:

同名成员最简单最安全的处理方式:加作用域

1.子类和父类 同名成员数据

子类默认优先访问子类的同名成员

必须加父作用域 访问父类的同名成员。

class Base
{
public:
	int a;
public:
	Base(int a)
	{
		this->a = a;
	}
};
class son :public Base
{
public:
	int a;
	son(int x, int y) :Base(x)
	{
		a = y;
	}
};
//这里同名,但优先是子类成员
int main()
{
	son a(10, 20);
	cout << a.a <

2.子类和父类 同名成员函数

class Base
{
public:
	void fun()
	{
		cout << "调用基类中fun" << endl;
	}
	int a;
};
class son :public Base
{
public:
	void fun()
	{
		cout << "调用派生类中fun" << endl;
	}
	
};
//这里同名,但优先是子类成员
int main()
{
	son a;
	a.fun();
	a.Base::fun();
	return 0;
}

c++学习之继承_第6张图片

 

 

你可能感兴趣的:(学习)