5.20
1、多态
关于基本的多态原理剖析
代码解释与验证
//多态基本语法
#include<iostream>
using namespace std;
//关于多态,动态多态父类的指针可以指向子类的对象
class Animal
{
public:
//最初传入一个父类的地址或引用,直接确定了地址空间
//void speak()
//{
// cout << "动物在说话" << endl;
//}
//通过虚函数来生成一个虚拟函数指针,虚拟函数指针指向虚拟函数表,函数表内为分类的各个函数,指针大小为四个字节
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
//子类通过继承将父类的虚拟函数指针和虚拟函数表都继承过来
class Cat :public Animal
{
public:
//当重写一份父类虚函数时,子类的虚拟函数表中的函数就被重写的函数所替换,及父类的虚函数替换成了重写的子类的虚函数
void speak()
{
cout << "小猫在说话" << endl;
}
};
class Dog :public Animal
{
public:
void speak()
{
cout << "小狗在说话" << endl;
}
};
//通过父类的指针指向子类从而来确定用父类的指针指向子类虚函数表中的子类虚函数,来完成动态多态过程
void doSpeak(Animal& animal)
{
animal.speak();
}
void test1()
{
Cat cat;
doSpeak(cat);
Dog dog;
doSpeak(dog);
}
int main()
{
test1();
system("pause");
return 0;
}
2、多态的计算器案例
//多态的计算机案例
#include<iostream>
using namespace std;
class Vcalaulator
{
public:
virtual int calculate()
{
return 0;
}
int m_a;
int m_b;
};
//加法运算
class Add :public Vcalaulator
{
public:
int calculate()
{
return m_a + m_b;
}
};
//减法运算
class Sub :public Vcalaulator
{
public:
int calculate()
{
return m_a - m_b;
}
};
int getresult(Vcalaulator& vc)
{
return vc.calculate();
}
//乘法运算
class Mul :public Vcalaulator
{
public:
int calculate()
{
return m_a * m_b;
}
};
//void test1()
//{
// Add add;
// add.m_a = 10;
// add.m_b = 20;
// int ret = add.calculate ();
// cout << ret << endl;
//}
//
//void test2()
//{
// Sub sub;
// sub.m_a = 40;
// sub.m_b = 29;
// int ret = getresult(sub);
// cout << ret << endl;
//}
//
//void test3()
//{
// Mul mul;
// mul.m_a = 32;
// mul.m_b = 17;
// int ret = getresult(mul);
// cout << ret << endl;
//}
void test11()
{
Vcalaulator* vc = new Add;
vc->m_a = 39;
vc->m_b = 45;
//父类指针指向虚拟函数,但是虚拟函数已经被子代的虚拟函数重写,这一步应该体现
cout << vc->calculate() << endl;
delete vc;//用完释放
//减法
vc = new Sub;
vc->m_a = 39;
vc->m_b = 45;
cout << vc->calculate() << endl;
}
int main()
{
//test1();
//test2();
//test3();
test11();
system("pause");
return 0;
}
这个部分体会到多态的核心应用在于通过父类指针指向子类,子类由于虚拟函数的重写覆盖了原本的父类虚拟函数,进而实现了一种动态多态,代码案例的编写应该体现出此过程
3、纯虚函数与抽象类
一个类中只要含有一个纯虚函数即为抽象类,抽象类不可以实例化对象
//纯虚函数与抽象类
#include<iostream>
using namespace std;
class Base
{
public:
//纯虚函数,只要有一个纯虚函数即为抽象类
virtual void func() = 0;
};
class Son :public Base
{
public:
//子类中必须重写父类的纯虚函数,这个实质就是将多态父类中的虚函数替换为纯虚函数而已
void func()
{
cout << "Son—func调用" << endl;
}
};
void test1()
{
//抽象类无法实例化对象
//Base base;
//Base* base = new Base;
Son s;
s.func();
Base* base = new Son;
base->func();
}
int main()
{
test1();
system("pause");
return 0;
}
4、饮品制作案例
//制作饮料案例
#include<iostream>
using namespace std;
class AbstractDrinking
{
public:
//煮水
virtual void boil() = 0;
//泡水
virtual void brew() = 0;
//入杯
virtual void incup() = 0;
//加佐料
virtual void addsth() = 0;
//制作饮料—公共接口函数,用此将父类虚拟指针指向子类虚拟函数这个过程结合起来
void makedrinking()
{
boil();
brew();
incup();
addsth();
}
};
class makecoffe :public AbstractDrinking
{
public:
void boil()
{
cout << "煮水" << endl;
}
void brew()
{
cout << "泡水" << endl;
}
void incup()
{
cout << "倒入杯中" << endl;
}
void addsth()
{
cout << "加点牛奶和糖" << endl;
}
};
class maketea :public AbstractDrinking
{
public:
void boil()
{
cout << "煮水" << endl;
}
void brew()
{
cout << "泡水" << endl;
}
void incup()
{
cout << "倒入杯中" << endl;
}
void addsth()
{
cout << "加点枸杞补补肾" << endl;
}
};
void test1()
{
AbstractDrinking* abs = new makecoffe;
abs->makedrinking();
delete abs;//用完释放
cout << "------------------------" << endl;
abs = new maketea;
abs->makedrinking();
}
int main()
{
test1();
system("pause");
return 0;
}
5、虚析构与纯虚析构
虚析构或析构不能使父类的指针调用子类的析构函数,纯虚析构可以解决这个问题,具体原理不太清晰,因为子类和父类的析构函数名称不一样,应该不是属于重写虚拟函数的原理
//虚析构与纯虚析构
#include<iostream>
using namespace std;
class Animal
{
public:
Animal()
{
cout << "Animal构造函数调用" << endl;
}
virtual void speak() = 0;
//单纯的虚析构函数不能使父类指针调用子类的析构函数
// ~Animal()
//{
// cout << "Animal虚析构函数调用" << endl;
//}
virtual ~Animal() = 0;
};
Animal::~Animal()
{
cout << "Animal纯虚析构函数调用" << endl;
}
class Cat :public Animal
{
public:
Cat(string name)
{
cout << "Cat构造函数调用" << endl;
m_name = new string(name);
}
void speak()
{
cout << *m_name << "小猫在喵喵叫" << endl;
}
~Cat()
{
cout << "Cat析构函数调用" << endl;
if (m_name != NULL)
{
delete m_name;
m_name = NULL;
}
}
string* m_name;
};
void test1()
{
Animal* animal = new Cat("Tom");
animal->speak();
delete animal;
}
int main()
{
test1();
system("pause");
return 0;
}
6、电脑组装案例
//电脑组装案例
#include<iostream>
using namespace std;
//电脑零件类
class CPU
{
public:
virtual void calculate() = 0;
};
class Memory
{
public:
virtual void storage() = 0;
};
class VideoCard
{
public:
virtual void display() = 0;
};
//组装电脑类
class Computer
{
public:
Computer(CPU* cpu,VideoCard* vd,Memory* mem)
{
m_cpu = cpu;
m_vd = vd;
m_mem = mem;
}
void makecomputer()
{
m_cpu->calculate();
m_vd->display();
m_mem->storage();
}
~Computer()
{
if (m_cpu != NULL)
{
delete m_cpu;
m_cpu = NULL;
}
if (m_vd != NULL)
{
delete m_vd;
m_vd = NULL;
}
if (m_mem != NULL)
{
delete m_mem;
m_mem = NULL;
}
}
private:
//纯虚类无法进行实例化,这地方考虑采用指针
CPU* m_cpu;
VideoCard* m_vd;
Memory* m_mem;
};
class Intelcpu:public CPU
{
public:
void calculate()
{
cout << "CPU开始处理" << endl;
}
};
class Intelvideocard :public VideoCard
{
public:
void display()
{
cout << "显卡开始显示" << endl;
}
};
class Intelmemory :public Memory
{
public:
void storage()
{
cout << "存储器开始存储" << endl;
}
};
void test1()
{
CPU* cpu = new Intelcpu;
VideoCard* vd = new Intelvideocard;
Memory* mem = new Intelmemory;
Computer* computer1 = new Computer(cpu,vd,mem);
computer1->makecomputer();
delete computer1;//用完释放
}
int main()
{
test1();
system("pause");
return 0;
}
基本思路,构造一个制作电脑的类,内部有一个makecomputer函数,该函数调用三个电脑零件类,三个零件类中都是虚拟函数,另创建三个厂商子类继承零件,大体完成整体代码建构