c++回顾(六)成员函数的重载、覆盖、隐藏以及继承

对类层次的同名成员函数来说,有三种关系:函数重载(overload)、函数覆盖(override)、函数隐藏(hide、oversee)

一、函数重载

重载的概念相对简单,只有在同一类定义中的同名成员函数才存在重载关系,特点是函数的参数和数目有所不同

比如:

void output(int a,int b);
void output(int a);

简单的讲,就是函数名相同,但是参数类型或者参数数目不同,来看一个构造函数重载的例子

#include<iostream>
using namespace std;

struct Point
{
	int x;
	int y;
	Point()//构造函数,注意没有任何返回值
	{
		x = 0;
		y = 0;
	}
	Point(int _x, int _y) :x(_x), y(_y){}//重载构造函数
	~Point()
	{
		cout << "再见" << endl;
	}
	void output()//成员函数
	{
		cout << "x="<<x << endl <<"y="<< y << endl;
	}

	
};
int main()
{
	Point p(5,10);//调用重载函数Point(int_x,int _y)

	p.output();
	system("pause");
    return 0;
}
//加颜色

结果输出:

二、成员函数覆盖

指在派生类中覆盖基类中的同名函数,要求基类函数必须是虚函数,且:

1)与基类的虚函数(vittual)有相同的参数个数

2)与基类的虚函数有相同的参数类型

3)与基类的虚函数有相同的返回类型

特征如下:

1)不同的范围(分别位于派生类和基类)

2)相同的函数名字;

3)相同的参数

4)基类函数必须要有 virtual关键字。

仔细一看,覆盖不是和重载差不多么?区别如下:

1)覆盖发生在子类和父类之间;重载是同一个类中不同方法之间的关系

2) 覆盖要求参数列表相同,重载要求参数列表不同;覆盖要求返回类型相同,重找则不要求

3)覆盖是根据对象的类型来决定的,重载是根据调用时实参表与形参表来选择的

三、成员函数的隐藏

隐藏是指派生类中屏蔽了基类中的同名函数,包括

1)两个函数参数相同,但是基类不是虚函数。看到这大家应该比较清楚,和覆盖的区别就是基类函数是否是虚函数。

2)两个函数参数不同,无论基类是否是虚函数,基类函数都会被隐藏,和重载不同的是不在同一类中。

四、继承

这边来看看具体例子讲解,理解继承就是理解面向对象编程的关键,

我们定义一个动物Animal属性,有吃、睡觉、呼吸(动物都具有这些属性),

struct Animal//动物的属性 吃、睡觉、呼吸
{
	void eat()
	{
		cout << "animal eat" << endl;
	}
	
	void sleep()
	{
		cout << "animal sleep" << endl;
	}
	void breathe()
	{
		cout << "animal sleep" << endl;
	}
};

,现在 鱼需要继承这些属性,那么鱼也有吃、睡觉、呼吸,总不能再定义一个类吧,那么我需要鱼继承animal属性

struct Fish :public Animal//public代表类继承访问特性
{

};

再看main函数,上面Animal为父类,Fish为子类


int main()
{
	Animal an;
	an.eat();
	Fish fh;
	fh.sleep();
	system("pause");
    return 0;
}

以上程序输出结果,动物吃动物睡觉,这就是继承

五、继承的相关特性

上面代码中我们看到

struct Fish :public Animal//public代表类继承访问特性
{

};

有个public,那么自然有protected和private,关于这个如下表

六、构造函数的调用顺序

1、单继承时

派生时,构造函数和析构函数是不能继承的,所以派生类需要重新定义构造函数和析构函数,并且的构造函数的初始化列表中,调用基类的构造函数,简单讲,先调用 父类的构造,再调用子类的构造。析构时,先调用子类的析构,再调用父类的析构,

如下例子:

#include<iostream>
using namespace std;


struct Animal//动物的属性 吃、睡觉、呼吸
{
	Animal()//父类的构造
	{
		cout << "animal construst" << endl;
	}
	~Animal()//父类的析构
	{

	}
	void eat()
	{
		cout << "animal eat" << endl;
	}
	
	void sleep()
	{
		cout << "animal sleep" << endl;
	}
	void breathe()
	{
		cout << "animal sleep" << endl;
	}
};

struct Fish :public Animal
{
	Fish()//子类的构造
	{
		cout << "fish construct" << endl;
	}
	~Fish()//子类的析构
	{

	}
};

int main()
{

	Fish fh;
	system("pause");
    return 0;
}

程序输出

来看看函数隐藏的情况

我们都知道,鱼睡觉是冒泡的,和动物不一样,来看看例子

#include<iostream>
using namespace std;


struct Animal//动物的属性 吃、睡觉、呼吸
{
	Animal()//父类的构造
	{
	//	cout << "animal construst" << endl;
	}
	~Animal()//父类的析构
	{

	}
	void eat()
	{
		cout << "animal eat" << endl;
	}
	
	void sleep()
	{
		cout << "animal sleep" << endl;
	}
	void breathe()
	{
		cout << "animal sleep" << endl;
	}
};

struct Fish :public Animal
{
	Fish()//子类的构造
	{
		//cout << "fish construct" << endl;
	}
	~Fish()//子类的析构
	{

	}
	void breathe()
	{
		cout << "fish bubu sleep" << endl;
	}
};

int main()
{

	Fish fh;
	fh.breathe();
	system("pause");
    return 0;
}

输出

如果我们希望即有动物的睡觉又冒泡呢?,那么需要在fish这改变一下

struct Fish :public Animal
{
	Fish()//子类的构造
	{
		//cout << "fish construct" << endl;
	}
	~Fish()//子类的析构
	{

	}
	void breathe()
	{
		Animal::breathe();//添加父类的呼吸
		cout << "fish bubu sleep" << endl;
	}
};

输出结果既有动物的睡觉,又有鱼的冒泡

还需要注意的是fish对象内存布局,在赋值fish地址时,其实是Animal地址,如果想调用fish地址,需要加vitual,就是把函数定义成虚函数,这边涉及c++的多态性。

多继承时,派生类的构造函数初始化列表需要调用各自基类的构造函数,:

注意,此时派生类的构造函数的初始化列表只能控制用于初始化基类的值,不能控制基类的构造次序。

基类构造函数按照基类构造函数在类派生表中的出现次数调用。析构函数是按照构造函数的逆序进行

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值