C++ 覆盖方法与重载方法
覆盖方法(overriding)
什么是类函数的覆盖方法:
覆盖方法用于同一函数的重写即派生类函数覆盖基类同名函数
覆盖方法重写(覆盖)了一个方法,以实现不同的功能.一般是用于子类在继承父类时,重写(重新实现)父类中的方法
覆盖方法的特征:
范围不同(分别位于 基类 和 派生类中)
函数名字相同
函数参数相同
基类函数必须有virtual(虚函数)关键字
为什么需要覆盖方法:
在 C++ 里,当我们需要在 基类里提供一个通用的函数,但是在它的某个子类里,需要修改这个方法(通用函数)的实现,就要用到覆盖方法
当父类中的某些方法不能满足要求时,子类中改写父类的方法
注意:
1.重写方法的 参数列表(方法名称,参数列表,返回类型)必须完全与被重写的方法相同否则不能称其为覆盖而是 重载
2.重写方法的 访问修饰符一定要大于被重写方法的访问修饰符(public>protected>default>private
)
3.重写的方法的返回值必须和被重写的方法的返回一致
3.被重写的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行重写
5.静态方法不能被重写为非静态的方法(会编译出错)
覆盖方法例程
#include <iostream>
#include <string>
using namespace std;
//todo覆盖方法
class Animal
{
public:
Animal(string name);
void eat();//基类中的eat()方法 因为monkey和turtle都具有eat的功能 所有选择此方法为被覆盖重写的通用方法
void sleep();
void run();
protected:
string thename;
};
class Monkey :public Animal//todo建立一个继承自Animal基类的子类Monkey
{
public:
Monkey(string name);
void climb();
void eat();//todo再一次声明基类中的通用函数eat()
//注意: 重写方法的参数列表必须完全与被重写的方法相同 否则不能称其为 覆盖 而是 重载
// 重写方法的访问修饰符一定要大于被重写方法的访问修饰符(public>protected>default>private)
// 重写的方法的返回值必须和被重写的方法的返回一致
// 被重写的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行重写
// 静态方法不能被重写为非静态的方法(会编译出错)
};
class Turtle :public Animal
{
public:
Turtle(string name);
void swim();
void eat();
};
//todo基类Animal的构造器定义与成员函数定义
Animal::Animal(string name)
{
thename = name;
}
void Animal::eat()//todo基类中的通用方法eat的定义
{
cout << "基类中状态 :吃东西" << endl;
}
void Animal::sleep()
{
cout << "基类中状态 :睡觉" << endl;
}
void Animal::run()
{
cout << "基类中状态 :跑动" << endl;
}
//todo子类Monkey的构造器定义与成员函数定义
Monkey::Monkey(string name) :Animal(name)
{
}
void Monkey::climb()
{
cout << "子类中monkey状态 :爬树" << endl;
}
void Monkey::eat()//todo继承基类Animal后的子类Monkey的 通用函数eat通用方法的覆盖
{
Animal::eat();
cout << "覆盖后monkey的eat状态 :'我在吃香蕉' " << endl;
}
//todo子类Turtle的构造器定义与成员函数定义
Turtle::Turtle(string name) :Animal(name)
{
}
void Turtle::swim()
{
cout << "子类中Turtle状态 :游泳" << endl;
}
void Turtle::eat()
{
Animal::eat();
cout << "覆盖后turtle的eat状态 :'我在吃水草' " << endl;
}
int main()
{
Monkey monkey("小猪猪");
Turtle turtle("小甲鱼");
//todo调用覆盖方法
monkey.eat();
turtle.eat();
monkey.climb();
turtle.swim();
return 0;
}
结果
重载方法(overload)
什么是类函数的重载方法:
对于类的方法(包括从父类中继承的方法), 方法名相同,参数列表不同的方法之间就构成了重载关系 ,这里有两个问题需要注意
1.参数列表又叫参数签名,指三样东西: 参数的类型,参数的个数,参数的顺序 ,这三者只要有一个不同就叫做参数列表不同
2.重载关系只能发生在同一个类中吗?非也,这时候你要深刻理解继承,要知道一个子类所拥有的成员除了自己显式写出来的以外,还有父类遗传下来的,所以子类中的某个方法和父类中继承下来的方法也可以发生重载的关系
为什么需要重载方法:
类重载机制使你可以定义多个同名的方法(函数),只是他们的输入参数必须不同(编译器是依靠不同的输入参数来区分不同的方法)
注意:🎯
对从基类继承来的方法进行重载,程序将永远编译不过(子类中不可重载继承自基类的方法) 因为如果在子类中进行基类中某方法的重新定义,就变成了覆盖方法 (进行覆盖前提是覆盖函数和被覆盖函数的函数名和参数列表一致)
重载方法例程
class Animal
{
public:
Animal(string name);
void eat();
void eat(string food);//todo基类中进行eat函数的重载
void eat(int count);//todo再次进行eat函数的重载
void sleep();
void run();
protected:
string thename;
};
class Monkey :public Animal
{
public:
Monkey(string name);
void climb();
//void eat(float a);
//todo如果在子类中进行基类中某方法的重新定义 就变成了覆盖方法 在具体定义此方法时 程序将会报错
};
class Turtle :public Animal
{
public:
Turtle(string name);
void swim();
};
//todo基类Animal的构造器定义与成员函数定义
Animal::Animal(string name)
{
thename = name;
}
void Animal::eat()
{
cout << "基类中状态 :吃东西" << endl;
}
void Animal::eat(string food)//todo基类中的函数eat进行重载
{
cout << "我吃的是"<<food << endl;
}
void Animal::eat(int count)//todo基类中的函数eat再次进行重载
{
cout << "我吃了" <<count<<"根"<< endl;
}
void Animal::sleep()
{
cout << "基类中状态 :睡觉" << endl;
}
void Animal::run()
{
cout << "基类中状态 :跑动" << endl;
}
//todo子类Monkey的构造器定义与成员函数定义
Monkey::Monkey(string name) :Animal(name)
{
}
void Monkey::eat(float a)
{
}
void Monkey::climb()
{
cout << "子类中monkey状态 :爬树" << endl;
}
//todo子类Turtle的构造器定义与成员函数定义
Turtle::Turtle(string name) :Animal(name)
{
}
void Turtle::swim()
{
cout << "子类中Turtle状态 :游泳" << endl;
}
int main()
{
Monkey monkey("小猪猪");
Turtle turtle("小甲鱼");
monkey.eat();
turtle.eat();
monkey.eat("香蕉");//调用重载函数一
monkey.eat(15);//调用重载函数二
return 0;
}
//https://www.jianshu.com/p/00b4fa11d63e
结果
总结:🎯
类函数的覆盖和重载具有以下相同点:
1.都要求类函数同名
2.都可以用于抽象类函数和非抽象类函数之间
类函数的覆盖和重载在使用时有以下区别:
1.覆盖 要求类函数的参数列表(参数签名)必须一致 重载 要求参数必须不一致
2.覆盖 要求返回类型必须一致 重载 没有要求
3.覆盖 只能用于子类覆盖基类的类函数 重载 同一个类的所有方法都会被重载 (包括从父类中继承而来的方法)但不可在子类中重载父类中的方法
4.覆盖 对方法的访问权限和抛出的异常有特殊要求 重载 没有限制
5.覆盖 父类中的一个方法只能被子类覆盖一次 重载 一个方法可以在所有类中被重载多次