抽象类和纯虚函数
多态的成立条件
- 有继承
- 子类重写父类的虚函数
- 返回值,函数名,函数参数,必须和父类完全一致(析构函数除外)
- 子类中virtual关键字可写可不写,建议写
- 类型兼容,父类指针,父类引用,指向子类对象。
抽象类和纯虚函数
在设计时,常常希望基类仅仅作为其派生类的一个接口,这就是说,仅对基类进行向上类型转换,使用它的接口,而不是直接对基类实例化,同时创建一个纯虚函数允许接口中放置成员函数。
要做到这点可以在基类中加入至少一个纯虚函数使得基类称为抽象类。
- 纯虚函数使用关键字virtual,并在其后面加上=0,如果试图去实例化一个抽象类,编译器会阻止这种操作。
virtual void func() = 0;
当继承一个抽象类的时候,必须实现所有的纯虚函数,否则由抽象类派生的类也是一个抽象类。
virtual void func() = 0;
告诉编译器在vtable中为函数保留一个位置,但在这个特定位置不放地址
开闭原则
面向对象设计原则之开闭原则 : 对扩展开放,对修改关闭。
优点:易于扩展,结构性好,可读性高。
缺点:效率稍低
实现多态中调用同名虚函数有两种方法,
第一种是申请指定类型的对象空间,再调用对象的方法。
第二种是通过重定义同名函数,传参形式调用,详见下面两个案例。
计算器案例
#include <string>
#include <iostream>
using namespace std;
#if 0
class Calculator
{
public:
void set1(int val)
{
val1 = val;
}
void set2(int val)
{
val2 = val;
}
int getResult(string oper)
{
if(oper == "+") return val1 + val2;
else if(oper == "-") return val1 - val2;
}
private:
int val1;
int val2;
};
#endif
//面向对象设计原则之开闭原则 : 对修改关闭,对扩展开放
//利用多态实现计算器
class abstractCalculator
{
public:
//virtual int getResult() { return 0; }
void set1(int val) { val1 = val; }
void set2(int val) { val2 = val; }
int get1() { return this->val1; }
int get2() { return this->val2; }
//如果父类中有纯虚函数,子类继承父类后必须实现纯虚函数
virtual int getResult() = 0;
private:
int val1;
int val2;
};
class PlusCalculator : public abstractCalculator
{
public:
virtual int getResult() { return get1() + get2(); }
};
class SubCalculator : public abstractCalculator
{
public:
virtual int getResult() { return get1() - get2(); }
};
class MultiCalculator : public abstractCalculator
{
public:
virtual int getResult() { return get1() * get2(); }
};
class DivCalculator : public abstractCalculator
{
public:
virtual int getResult() { return get1() / get2(); }
};
void test02()
{
abstractCalculator * abc;
abc = new PlusCalculator;
abc->set1(10);
abc->set2(5);
cout << abc->getResult() << endl;
}
void test03()
{
abstractCalculator * abc;
abc = new SubCalculator;
abc->set1(10);
abc->set2(5);
cout << abc->getResult() << endl;
}
void test04()
{
abstractCalculator * abc;
abc = new MultiCalculator;
abc->set1(10);
abc->set2(5);
cout << abc->getResult() << endl;
}
void test05()
{
abstractCalculator * abc;
abc = new DivCalculator;
abc->set1(10);
abc->set2(5);
cout << abc->getResult() << endl;
}
int main()
{
test04();
test05();
return 0;
}
求面积案例
#include <iostream>
using namespace std;
const double PI = 3.14;
class Figure
{
public:
virtual void display() const = 0;
virtual double area() const = 0;
};
class Rectangle : public Figure
{
public:
Rectangle(size_t length, size_t width):_length(length), _width(width){}
void display() const { cout << "Rectangle"; }
double area() const { return _length * _width; }
private:
size_t _length;
size_t _width;
};
class Circle : public Figure
{
public:
Circle(double radius):_radius(radius){}
void display() const { cout << "Circle"; }
double area() const { return PI * _radius * _radius; }
private:
double _radius;
};
void display(Figure & fig)
{
fig.display();
cout << "'s area is " << fig.area() << endl;
}
int main()
{
Rectangle rectangle(3, 4);
Circle circle(5);
display(rectangle);
display(circle);
return 0;
}