C++学习笔记 —— 多态

什么是多态

父类引用或者指针指向子类对象。

编译时多态(静态连编):函数和运算符重载。编译阶段就确定了地址。
运行时多态(动态连编):通常说的多态。

多态的使用

使用条件:

  1. 父类中函数为虚函数
  2. 子类继承父类并重写该虚函数,子类virtual可写可不写
  3. 父类指针或引用指向子类对象,然后调用方法。

也就是说C++中如果要实现多态,函数必须为虚函数,而使用虚函数,也就是为了实现多态。尽量不要重写父类的普通函数。
而定义函数为纯虚函数是为了子类必须重写该函数。说明该类是一个接口,

静态连编

#include <iostream>

using namespace std;

class Animal

{
public:
	void speak()
	{
		cout << "动物" << endl;
	}
};

class Cat : public Animal
{
public:
	//子类重写父类方法
	void speak() //子类中virtual可写可不写
	{
		cout << "小猫" << endl;
	}
};

void doSpeak(Animal &animal){
	animal.speak();
}
int main()
{
	Cat cat;//创建cat对象并传入方法,cat是animal的子类,所以可以认为cat是animal的一种类型
	//所以可以把cat传进去
	doSpeak(cat);//动物  但是这里调用的还是父类的方法,因为没有产生多态,是静态编译,只有用virtual才能产生多态
	Animal &a1 = cat1;
	a1.speak();//动物

	Animal *a2 = new Cat;
	a2->speak();//动物
}

动态连编

#include <iostream>

using namespace std;

class Animal

{
public:
	void virtual speak()
	{
		cout << "动物" << endl;
	}
};

class Cat : public Animal
{
public:
	//子类重写父类方法
	void speak()
	{
		cout << "小猫" << endl;
	}
};

void doSpeak(Animal &animal){
	animal.speak();
}
int main()
{
	Cat cat1;
	doSpeak(cat1);//小猫 使用了virtual所以为动态连编,为多态

	Animal &a1 = cat1;
	a1.speak();//小猫

	Animal *a2 = new Cat;
	a2->speak();//小猫	
}

多态的好处

C++ 什么是多态,多态的用途

Animal *a2 = new Cat;
a2->speak();//小猫	

比如这句话,我们可以根据我们的需要来创建不同对象,我们可以创建小猫,小狗,小猪,然后把它给animal。然后animal调用speak就可以实现多态,也就是根据创建的不同对象调用不同对象中的speak方法。“一个接口,多种方法”,程序在运行时才决定调用的函数。接口重用。

代码的原则:修改关闭,扩展开放。

计算器例子

#include <iostream>

using namespace std;

class Calculator
{
public:
	int v1;
	int v2;
	void setv1(int v)
	{
		v1 = v;
	}
	void setv2(int v)
	{
		v2 = v;
	}
	int virtual getResult()
	{
		return v1 + v2;
	}
};

class PlusCalculator : public Calculator
{
	int virtual getResult()
	{
		return v1 + v2;
	}
};

class SubCalculator : public Calculator
{
	int virtual getResult()
	{
		return v1 - v2;
	}
};

int main()
{
	Calculator *calculator;
	//使用加法计算器
	calculator = new PlusCalculator;
	calculator->setv1(10);
	calculator->setv2(20);
	cout << calculator->getResult() << endl; //30

	delete calculator; //清除

	//使用减法计算器
	calculator = new SubCalculator;
	calculator->setv1(10);
	calculator->setv2(20);
	cout << calculator->getResult() << endl;

}

如果我们需要继续扩展添加乘法计算器,就直接添加,使用的方式和上面一样,扩展非常方便。这就是多态的好处。结构性好,可读性高。
C++比C语言效率低,其实就是在多态上,因为内部结构复杂了,就比c语言低一点点。

纯虚函数和抽象类

接着上面的例子,我们可以把父类的函数作为一个纯虚函数。作用和上面一样实现多态。

  1. 当一个类有纯虚函数时,这个类就为抽象类,不能实例化。相当于一个接口,只做多态使用而不能创建该类对象。
  2. 子类必须重写实现所有纯虚函数,不然子类也是一个抽象类,不能实例化。
class Calculator
{
public:
	int v1;
	int v2;
	void setv1(int v)
	{
		v1 = v;
	}
	void setv2(int v)
	{
		v2 = v;
	}
	//纯虚函数:子类必须重写此函数
	//这个类为抽象类,该类无法实例化;
	int virtual getResult() = 0; 
};

虚析构和纯虚析构

当我们继承的时候,父类指针指向子类对象,然后释放父类,则只创建了子类对象,而没有释放子类对象。这样会导致释放不干净内存问题。

#include <iostream>

using namespace std;

class Calculator
{
public:
	Calculator()
	{
		cout << "计算器构造" << endl;
	}
	~Calculator()
	{
		cout << "计算器析构" << endl;
	}
};

class PlusCalculator : public Calculator
{
public:
	PlusCalculator()
	{
		cout << "加法计算器构造" << endl;
	}
	~PlusCalculator()
	{
		cout << "加法计算器析构" << endl;
	}
};

int main()
{
	Calculator *calculator;
	//使用加法计算器
	calculator = new PlusCalculator;

	delete calculator; 
}
/*
计算器构造
加法计算器构造
计算器析构
*/

解决问题:使用虚析构

#include <iostream>

using namespace std;

class Calculator
{
public:
	Calculator()
	{
		cout << "计算器构造" << endl;
	}
	virtual ~Calculator()
	{
		cout << "计算器析构" << endl;
	}
};

class PlusCalculator : public Calculator
{
public:
	PlusCalculator()
	{
		cout << "加法计算器构造" << endl;
	}
	virtual ~PlusCalculator()
	{
		cout << "加法计算器析构" << endl;
	}
};

int main()
{
	Calculator *calculator;
	//使用加法计算器
	calculator = new PlusCalculator;

	delete calculator; 
}
/*
计算器构造
加法计算器构造
加法计算器析构
计算器析构
*/

虚析构也可以定义为纯虚析构,但是需要类内声明,类外必须实现,如果析构函数为纯虚析构,则该类为抽象类,不能实例化。
也就是说如果析构函数是纯虚析构则该类肯定为抽象类。

向上转型和向下转型

向下转型

父类转为子类,叫做向下转型,是不安全的。
因为子类东西多,父类东西少,父类转为子类是不安全的。

Animal *animal = new Animal;
Cat *cat = (Cat*) animal; // 把父类转为子类

向上转型

子类转为父类,是安全的,向上转型,父类东西少,是安全的。

Cat *cat = new Cat;
Animal *animal = (Animal*) cat; // 把父类转为子类

发生了多态

如果发生类多态,则向下转换也是安全的。

Animal *animal = new Cat;
Cat *cat = (Cat*) animal;
发布了103 篇原创文章 · 获赞 94 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/chongbin007/article/details/104416574