基于32位操作系统
文章目录
多态概念
举例
一个主人养了猫和狗,猫和狗都有自己爱吃的东西,主人在喂它们的时候,如果既要判断是猫还是狗,再判断他们分别爱吃什么,就显得很麻烦。如果主人养了很多种动物,这样的重复判断,就会浪费很多时间。
多态就是我们让每种食物和动物联系起来, 就相当于在动物的脸上贴上的动物喜欢吃的食物,在食物上面贴上哪种动物爱吃。这样让动物和植物有机的结合在了一起。提高了喂养的效率。
概念:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。简单的说:就是用基类的引用指向子类的对象
为什么要用多态呢?
原因:我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态除了代码的复用性外,还可以解决项目中紧偶合的问题,提高程序的可扩展性.。耦合度讲的是模块模块之间,代码代码之间的关联度,通过对系统的分析把他分解成一个一个子模块,子模块提供稳定的接口,达到降低系统耦合度的的目的,模块模块之间尽量使用模块接口访问,而不是随意引用其他模块的成员变量。
多态有什么好处?
- 应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。大大提高程序的可复用性。//继承
- 派生类的功能可以被基类的方法或引用变量所调用,这叫向后兼容,可以提高可扩充性和可维护性。//多态的真正作用,
如何实现多态
构成多态条件:
- 必须通过基类的指针或者引用调用虚函数
- 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
虚函数
我们将被virtual修饰的函数叫做虚函数(与虚继承使用同一个关键字,但是没有其他关系)
virtual void BuyTicket() {
std::cout << "Student Buy" << std::endl;
}
虚函数的重写
虚函数的重写(覆盖)就是派生类中有一个跟基类完全相同的虚函数称子类的虚函数重写了基类的虚函数。(协变允许返回值不同)
我们用一个没有重写的例子和重写的例子分别进行探讨。
代码如下:
没有virtual关键字
namespace test1 {
class Person {
public:
void BuyTicket() {
std::cout << "Person Buy" << std::endl;
}
};
class Student : public Person {
public:
void BuyTicket() {
std::cout << "Student Buy" << std::endl;
}
};
void Func(Person& p) {
p.BuyTicket();
}
void mytest() {
Person p;
Student s;
Func(p);
Func(s);
}
};
运行结果
无法访问派生类的同名函数
加上virtual关键字:
namespace test2 {
class Person {
public:
virtual void BuyTicket() {
std::cout << "Person Buy" << std::endl;
}
};
class Student : public Person {
public:
virtual void BuyTicket() {
//叫做覆盖或者重写
std::cout << "Student Buy" << std::endl;
}
};
void Func(Person& p) {
//必须通过指针或者引用调用虚函数
p.BuyTicket();
}
void mytest() {
Person p;
Student s;
Func(p);
Func(s);
}
};
运行结果:
实现多态
协变
协变是一种允许重写的函数返回值不同的操作,派生类重写基类虚函数时,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用时称为协变。
namespace test3 {
//协变 允许返回值不同
class A{
};
class B : public A{
};
class Person {
public :
virtual A* f() {
return new A;
}
};
class Student : public Person {
public:
virtual B