1.多态的基本语法
1.动态多态满足条件:
- 有继承关系;
- 子类要重写(函数返回值、函数名、参数列表完全相同)父类的虚函数;
动态多态的使用:
- 父类的指针或者引用,执行子类对象
#include<iostream>
using namespace std;
class Animal
{
public:
virtual void speak()
{
cout << "It's Animal." << endl;
}
};
class Cat :public Animal
{
public:
void speak()
{
cout << "It's a Cat." << endl;
}
};
class Dog :public Animal
{
public:
void speak()
{
cout << "It's a Dog." << endl;
}
};
//地址早绑定:在编译阶段确定函数地址
void doSpeak(Animal& animal) //Animal& animal = cat;
{
animal.speak();
}
//如果想指向让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,即地址晚绑定(virtual)
void test01()
{
Cat cat;
doSpeak(cat);
Dog dog;
doSpeak(dog);
}
int main()
{
system("pause");
return 0;
}
2.多态案例一计算器类
1.多态的优点:
- 代码组织结构清晰
- 可读性强
- 利于前期和后期的扩展以及维护
2.在真实开发中,提倡开闭原则(对扩展进行开放,对修改进行关闭)
#include<iostream>
using namespace std;
class AbstractCalculator
{
public:
virtual int getResult()
{
return 0;
}
int m_Num1; //操作数1
int m_Num2; //操作数2
};
class AddCalculator :public AbstractCalculator
{
int getResult()
{
return m_Num1 + m_Num2;
}
};
class SubCalculator :public AbstractCalculator
{
int getResult()
{
return m_Num1 - m_Num2;
}
};
class MulCalculator :public AbstractCalculator
{
int getResult()
{
return m_Num1 * m_Num2;
}
};
void test02()
{
//多态使用条件——父类指针或者引用指向子类对象
//加法
AbstractCalculator* abc = new AddCalculator;
abc->m_Num1 = 10;
abc->m_Num2 = 10;
cout << abc->getResult() << endl;
//用完后记得销毁
delete abc;
//减法
abc = new AddCalculator;
abc->m_Num1 = 10;
abc->m_Num2 = 10;
cout << abc->getResult() << endl;
//用完后记得销毁
delete abc;
}
int main()
{
test02();
system("pause");
return 0;
}
3.纯虚函数和抽象类
1.纯虚函数语法:virtual 返回值类型 函数名 {参数列表} = 0;当类中出现了纯虚函数,这个类也称为抽象类
2.抽象类特点:无法实例化对象;子类必须重写抽象类中的纯虚函数,否则也属于抽象类
#include<iostream>
using namespace std;
class Base
{
public:
//纯虚函数,该类为抽象类,无法实例化对象,其子类必须重写父类中的纯虚函数,否则也为抽象类
virtual void func() = 0;
};
class Son :public Base
{
public:
virtual void func()
{
cout << "SON" << endl;
}
};
void test03()
{
Base* base = new Son;
base->func();
}
int main()
{
test03();
system("pause");
return 0;
}
4.案例二 - 制作饮品
#include<iostream>
using namespace std;
class AbstractDrinking
{
public:
//煮水
virtual void Boil() = 0;
//冲泡
virtual void Brew() = 0;
//倒入杯中
virtual void PourInCup() = 0;
//加入辅料
virtual void PutSomething() = 0;
//制作饮品
void makeDrink()
{
Boil();
Brew();
PourInCup();
PutSomething();
}
};
//制作咖啡
class Coffee :public AbstractDrinking
{
public:
virtual void Boil()
{
cout << "农夫山泉有点甜" << endl;
}
virtual void Brew()
{
cout << "冲泡咖啡" << endl;
}
virtual void PourInCup()
{
cout << "倒入杯中" << endl;
}
virtual void PutSomething()
{
cout << "加糖" << endl;
}
};
//制作茶水
class Tea :public AbstractDrinking
{
public:
virtual void Boil()
{
cout << "开水" << endl;
}
virtual void Brew()
{
cout << "冲泡茶叶" << endl;
}
virtual void PourInCup()
{
cout << "倒入杯中" << endl;
}
virtual void PutSomething()
{
cout << "加点枸杞" << endl;
}
};
void doWork(AbstractDrinking * abs)
{
abs->makeDrink();
delete abs;
}
void test04()
{
doWork(new Coffee);
doWork(new Tea);
}
int main()
{
test04();
system("pause");
return 0;
}
5.虚析构和纯虚析构
1.虚析构和纯虚析构
- 可以解决父类指针释放子类对象
- 都需要有具体的函数实现
2。虚析构和纯虚析构区别:
- 如果是纯虚析构,该类属于抽象类,无法实例化对象
#include<iostream>
using namespace std;
class Animal
{
public:
Animal()
{
cout << "Animal构造" << endl;
}
//父类的指针在析构的时候,不会调用子类中的析构函数,可以利用虚析构解决该问题
virtual ~Animal()
{
cout << "Animal析构" << endl;
}
//virtual `Animal() = 0; 纯虚析构步骤一(需要声明)
virtual void speak() = 0;
};
//Animal::~Aniaml(){} 纯虚析构步骤二(也需要实现)
class Cat :public Animal
{
public:
Cat(string name)
{
cout << "CAT构造" << endl;
m_Name = new string(name);
}
virtual void speak()
{
cout << *m_Name << "is a cat" << endl;
}
string* m_Name;
~Cat()
{
if (m_Name != NULL)
{
cout << "CAT析构" << endl;
delete m_Name;
m_Name = NULL;
}
}
};
void test05()
{
Animal* animal = new Cat("Tom");
animal->speak();
delete animal;
}
int main()
{
test05();
system("pause");
return 0;
}