里氏替换原则: 子类可以扩展父类的功能,但不能改变父类原有的功能,不要重写父类的方法。
原因:如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差。
实现思想:取消原来的继承关系,重新设计它们之间的关系。
具体示例:
燕子会飞,几维鸟不会飞,其速度为0,计算两者飞行速度。UML类图如下
第一步:添加 bird.h
代码语言:javascript复制#pragma once//这个是必须的,不然子类没法引用的
#include <iostream>
using namespace std;
class Bird
{
public:
void setspeed(double speed){bird_speed=speed;}
double gettime(double dis){return (dis/bird_speed);}
public:
double bird_speed;
};
第二步:添加swallow.h
代码语言:javascript复制#include "bird.h"
class Swallow:public Bird
{
};
第三步:添加 brownkiwi.h
代码语言:javascript复制#include "bird.h"
class BrownKiwi: public Bird
{
public:
void setspeed(double speed){bird_speed=0;}
};
第四步:实现 main.cpp
代码语言:javascript复制#include "swallow.h"
#include "brownkiwi.h"
#include "bird.h"
#include <csignal>
#include <cmath>
#include "notbird_brownkiwi.h"
//异常处理
void output(double x,double y)
{
if( isinf(x))
throw x;
if(isinf(y))
throw y;
if(!isinf(x) && !isinf(y))
{
cout<<"燕子飞行了:"<<x<<" 小时"<<endl;
cout<<"几维鸟飞行了:"<<y<<" 小时"<<endl;
}
}
int main()
{
//父类指针指向子类对象
//这样定义不对
// Bird *bird1=new Swallow();
// Bird *bird2=new BrownKiwi();
//父类指针指向子类对象
/* Swallow bird1_;
BrownKiwi bird2_;
Bird* bird1=&bird1_;
Bird* bird2=&bird2_;
//转化为父类对象
Bird _bird2=*bird2;*/
//定义子类对象
Swallow* bird1=new Swallow();
BrownKiwi* bird2=new BrownKiwi();//
bird1->setspeed(120);
bird2->setspeed(120);
cout<<"飞行300公里"<<endl;
// _bird2.setspeed(120);
double x=bird1->gettime(300);
double y=bird2->gettime(300);
try
{
output(x,y);
// cout<<"几维鸟飞行了:"<<_bird2.gettime(300)<<" 小时"<<endl;
}
catch (double)
{
std::cerr << "除数是0! 发生错误!" << std::endl;
}
return 0;
}
结果显示:
运行错误:几维鸟类重写了鸟类的 setspeed方法,违背了里氏替换原则。
正确做法:取消几维鸟原来的继承关系,定义鸟和几维鸟的更一般的父类,如动物类,它们都有奔跑的能力。几维鸟的飞行速度虽然为0,但奔跑速度不为 0。修改后的UML类如下所示。
第五步:添加 anmial.h
代码语言:javascript复制#pragma once//这个是必须的,不然子类没法引用的
class Animal
{
public:
void setspeed(double speed){this->_speed=speed;}
double gettime(double dis){return dis/_speed;}
private:
double _speed;
};
第六步: 重新定义notbird_brownkiwi.h
代码语言:javascript复制#include "animal.h"
class NotBirdBrownKiwi: public Animal
{
};
第七步: 修改 main.cpp
代码语言:javascript复制 NotBirdBrownKiwi* bird2=new NotBirdBrownKiwi();//调用的是子类的方法
结果显示: