抽象类
抽象类和普通类有什么区别?
- 抽象类一般不是用来抽象某一个实体类型,抽象类不能实例化对象,但是可以定义指针或者引用变量。普通类定义指针或者引用变量或者实例化对象都可以。
一般把什么类设计成抽象类? 基类
动物的基类本身就算是泛指,
类->抽象一个实体的类型
这里还用上一节的例子:
定义Animal的初衷,并不是让Animal抽象某个实体的类型
定义基类的好处:
- string _name; 让所有的动物实体类通过继承Animal直接复用该属性
- 给所有的派生类保留统一的覆盖/重写接口
纯虚函数
我们定义了一个Animal,我们不知道是什么动物,当然也不知道它是怎么叫的。它里面的方法是给所有派生类保留的统一的重写接口。
我们不知道Animal的方法该怎么写,所以我们直接让这个基类的方法等于0,这个函数就叫做纯虚函数了。
拥有纯虚函数的类,叫做抽象类!(Animal此时就是抽象类了)
Animal a; 是不可以的!!!
抽象类不能再实例化对象了,但是可以定义指针和引用变量
#include <iostream>
using namespace std;
//动物的基类
class Animal
{
public:
Animal(string name) :_name(name) {}
//纯虚函数
virtual void bark() = 0; //叫
protected:
string _name;//动物的名称
};
//以下是动物的实体类
class Cat : public Animal
{
public:
Cat(string name) :Animal(name) {}
void bark() { cout << _name << " bark: miao miao!" << endl; }
};
class Dog : public Animal
{
public:
Dog(string name) :Animal(name) {}
void bark() { cout << _name << " bark: wang wang!" << endl; }
};
class Pig : public Animal
{
public:
Pig(string name) :Animal(name) {}
void bark() { cout << _name << " bark: heng heng!" << endl; }
};
void bark(Animal* p)
{
p->bark();//编译时看到Animal::bark是虚函数,就进行动态绑定
/*
p->cat Cat vftable &Cat::bark
p->dog Dog vftable &Dog::bark
p->pig Pig vftable &Pig::bark
*/
}
int main()
{
Cat cat("猫咪");
Dog dog("二哈");
Pig pig("佩奇");
bark(&cat);
bark(&dog);
bark(&pig);
return 0;
}
2、抽象类的第2个例子
//汽车的基类
class Car//抽象类
{
public:
Car(string name, double oil) :_name(name), _oil(oil) {}
//获取汽车剩余油量还能跑的公里数
double getLeftMiles()//这里是静态绑定
{
//1L油可以跑多少公里*剩余的油量 10 * oil
return _oil * this->getMilesPerGallon();//在这里发生动态绑定了
}
string getName()const { return _name; }
protected:
string _name;
double _oil;
virtual double getMilesPerGallon() = 0;//纯虚函数,保护,派生类可以访问,外部不能访问
//不同汽车 1L油可以跑多少公里 的数是不一样的
};
class Bnze : public Car
{
public:
Bnze(string name, double oil) :Car(name, oil) {}
double getMilesPerGallon() { return 20.0; }
};
class Audi : public Car
{
public:
Audi(string name, double oil) :Car(name, oil) {}
double getMilesPerGallon() { return 18.0; }
};
class BMW : public Car
{
public:
BMW(string name, double oil) :Car(name, oil) {}
double getMilesPerGallon() { return 19.0; }
};
//给外部提供一个同一的获取汽车剩余路程数的API
void showCarLeftMiles(Car &car)
{
cout<<car.getName() << " left miles:"
<< car.getLeftMiles() << "公里" <<endl;
//静态绑定 call Car::getLeftMiles()
}
int main()
{
Bnze b1("奔驰", 20.0);
Audi a("奥迪", 20.0);
BMW b2("宝马", 20.0);
showCarLeftMiles(b1);
showCarLeftMiles(a);
showCarLeftMiles(b2);
return 0;
}