【C++】关于多态详细解释_抽象类解释

如何解释多态

静态(编译时期)的多态:

    函数重载:在同一作用域底下,函数名字相同相同,但是函数的参数不同的一组函数称之为一组重载函数。

    模板(函数模板,类模板):使用template<typename T>形式的格式化类型,这样写完之后,增加代码的复用性。

     在编译阶段就决定了用那个函数

动态(运行时期)的多态:

  在继承结构中,基类指针(引用)指向派生类对象,通过该指针(引用)调用同名覆盖方法(虚函数)
,基类指针指向哪个派生类对象,就会调用哪个派生类对象的同名覆盖方法,称为多态
多态底层是通过动态绑定来实现的,pbase-》访问谁的vfptr=》继续访问谁的vftable
                                =》当然调用的是对应的派生类对象的方法了

 

继承的好处

1.可以做代码的复用

2.在基类中给所有派生类提供统一的虚函数接口,让派生类进行重写,然后就可以使用多态了。

比如动物的基类

// 动物的基类
class Animal
{
public:
	Animal(string name) :_name(name) {}
	virtual void bark() {}
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; }
};
/*
下面的一组bark API接口无法做到我们软件涉及要求的“开-闭“原则
软件设计由六大原则   “开-闭“原则  对修改关闭,对扩展开放
*/
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;
}

一般把什么类设置成抽象类?

解答:基类。

定义Animal的初衷,并不是让Animal抽象某个实体的类型
1.string _name; 让所有的动物实体类通过继承Animal直接复用该属性
2.给所有的派生类保留统一的覆盖/重写接口

 

拥有纯虚函数的类,叫做抽象类!(Animal)
Animal a; No!!!
抽象类不能再实例化对象了,但是可以定义指针和引用变量

修改过后的代码

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虚函数,动态绑定了 
}

// 汽车的基类
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; // 纯虚函数
};
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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值