多态
class Animal
{
public:
void speak()
{
cout << "动物在说话" << endl;
}
};
class Cat: public Animal
{
void speak()
{
cout << "小猫在说话" << endl;
}
};
// 因为地址早绑定了 所以在编译阶段就确定了函数的地址
void doSpeak(Animal &animal)
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
}
int main()
{
test01();
}
// 因为地址早绑定了 所以在编译阶段就确定了函数的地址 所以最后的输出结果为动物在说话
若想执行让猫说话 则这个函数地址就不可以提前绑定 需要在运行阶段再进行绑定
/* 动态多态的满足条件
1 有继承关系
2 子类重写父类的虚函数 重写(函数返回值的类型 函数名 参数列表 均要完全相同)
动态的多态使用
父类的指针或是引用 指向子类的对象
*/
class Animal
{
public:
virtual void speak()// 函数面前加上virtual关键字 变成虚函数 那么编译器在编译的时候 就不能确定函数的地址了
{
cout << "动物在说话" << endl;
}
};
class Cat: public Animal
{
void speak()
{
cout << "小猫在说话" << endl;
}
};
void doSpeak(Animal &animal)
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
}
int main()
{
test01();
}
// 运行结果为猫在说话
多态的原理
当基类中的成员函数变成了虚函数后 这个类中就会有一个虚函数(表)指针 指向的是虚函数的地址 当子类没有重写父类的虚函数的时候 就会继承父类的虚函数的指针 指针指向的是腐恶开中虚函数的地址 而当子类重写了父类的虚函数后 也会有一个指针 但是指向的已经不是父类中虚函数的地址了 而是子类中自己重写的那个函数的地址
多态案例
普通实现
class Calcular
{
public:
int m_num1;
int m_num2;
int getresult(string opr)
{
if (opr == "+")
return m_num1 + m_num2;
else if (opr == "-")
{
return m_num1 - m_num2;
}
else if (opr == "*")
return m_num1 * m_num2;
}
/* 如果想要去扩展新的功能 需要修改源码
而在真实的开发中 提倡开闭原则
也就是 对扩展进行开发 对修改进行关闭
*/
};
void test01()
{
Calcular c1;
c1.m_num1 = 10;
c1.m_num2 = 20;
cout << "m_num1" << "+" << "m_num2 = " << c1.getresult("+") << endl;
}
int main()
{
test01();
}
多态进行实现
class Calcular
{
public:
int m_num1;
int m_num2;
virtual int result()
{
return 0;
}
};
class AddCalcular : public Calcular
{
public:
int result()
{
return m_num1 + m_num2;
}
};
class SubCalcular:public Calcular
{
public:
int result()
{
return m_num1 - m_num2;
}
};
class MulCalcular :public Calcular
{
public:
int result()
{
return m_num1 * m_num2;
}
};
/*多态的好处
1 组织结构清晰
2 可读性强
3 对于前期和后期扩展以及维护性很高
*/
void test01()
{
AddCalcular c1;
c1.m_num1 = 20;
c1.m_num2 = 200;
cout << c1.m_num1 << "+" << c1.m_num2 << "= " << c1.result();
}
int main()
{
test01();
}
纯虚函数和抽象类
/*
抽象类的特点
1 无法实例化对象
2 抽象类的子类必须重写父类中的纯虚函数 否则也无法实例化对象 因为子类也会是抽象类
*/
class Calcular
{
public:
int m_num1;
int m_num2;
//纯虚函数
virtual int result() = 0;
};
class AddCalcular : public Calcular
{
public:
int result()
{
return m_num1 + m_num2;
}
};
class SubCalcular:public Calcular
{
public:
int result()
{
return m_num1 - m_num2;
}
};
class MulCalcular :public Calcular
{
public:
int result()
{
return m_num1 * m_num2;
}
};
/*多态的好处
1 组织结构清晰
2 可读性强
3 对于前期和后期扩展以及维护性很高
*/
void test01()
{
//Calcular c1;错误 抽象类无法实例化对象
//new Calcular; 错误 抽象类无法实例化对象
AddCalcular c1;
c1.m_num1 = 20;
c1.m_num2 = 200;
cout << c1.m_num1 << "+" << c1.m_num2 << "= " << c1.result() << endl;
Calcular* c2 = new SubCalcular; // 通过父类的指针 指向子类的对象
c2->m_num1 = 100;
c2->m_num2 = 12;
cout << c2->m_num1 << "-" << c2->m_num2 << "= " << c2->result() << endl;
delete c2; // 内存记得释放
}
int main()
{
test01();
}
多态案例2
class AbstractDrink
{
public:
virtual void Biol() = 0;
virtual void Brew() = 0;
virtual void PourIncup() = 0;
virtual void PutSomething() = 0;
void MakeDrink()
{
Biol();
Brew();
PourIncup();
PutSomething();
}
};
class Coffee :public AbstractDrink
{
virtual void Biol()
{
cout << "煮自来水" << endl;
}
virtual void Brew()
{
cout << "冲泡咖啡" << endl;
}
virtual void PourIncup()
{
cout << "倒入杯中" << endl;
}
virtual void PutSomething()
{
cout << "加入布丁" << endl;
}
void MakeDrink()
{
Biol();
Brew();
PourIncup();
PutSomething();
}
};
class Tea :public AbstractDrink
{
virtual void Biol()
{
cout << "煮自来水" << endl;
}
virtual void Brew()
{
cout << "冲泡茶叶" << endl;
}
virtual void PourIncup()
{
cout << "倒入杯中" << endl;
}
virtual void PutSomething()
{
cout << "加入柠檬" << endl;
}
void MakeDrink()
{
Biol();
Brew();
PourIncup();
PutSomething();
}
};
void DoDrink(AbstractDrink* drink)
{
drink->MakeDrink();
delete drink; // 释放内存
}
void test01()
{
DoDrink(new Coffee);
}
int main()
{
test01();
}
虚析构和纯虚析构
class Animal
{
public:
Animal()
{
cout << "Animal构造函数的调用" << endl;
}
virtual void Speak() = 0;
//virtual ~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;
}
string* m_name;
~Cat()
{
cout << "Cat析构函数的调用" << endl;
if (m_name != NULL)
{
delete m_name;
m_name = NULL;
}
}
};
void test01()
{
Animal* c1 = new Cat("小灰");
c1->Speak();
// 父类指针在析构的时候 不会调用子类中的析构函数 导致如果子类中如果有堆区的数据 就会导致内存的泄露
delete c1;
}
int main()
{
test01();
}
多态案例3
class CPU
{
public:
virtual void calcular() = 0;
};
class VideoCard
{
public:
virtual void display() = 0;
};
class Memory
{
public:
virtual void storage() = 0;
};
class LenovoCPU : public CPU
{
public:
void calcular()
{
cout << "联想的CPU正在计算" << endl;
}
};
class LenovoVideoCard : public VideoCard
{
public:
void display()
{
cout << "联想的显卡正在工作" << endl;
}
};
class LenovoMemory : public Memory
{
public:
void storage()
{
cout << "联想的内存正在储存" << endl;
}
};
class InterCPU :public CPU
{
void calcular()
{
cout << "因特尔的CPU正在计算" << endl;
}
};
class InterVideoCard : public VideoCard
{
void display()
{
cout << "因特尔的显卡正在工作" << endl;
}
};
class InterMemory :public Memory
{
void storage()
{
cout << "因特尔的内存正在储存" << endl;
}
};
class AppleCPU :public CPU
{
void calcular()
{
cout << "苹果的CPU正在计算" << endl;
}
};
class AppleVideoCard : public VideoCard
{
void display()
{
cout << "苹果的显卡正在工作" << endl;
}
};
class AppleMemory : public Memory
{
void storage()
{
cout << "苹果的内存正在储存" << endl;
}
};
class Computer
{
public:
Computer(CPU* c1, VideoCard* v1, Memory* m1)
{
m_c1 = c1;
m_v1 = v1;
m_m1 = m1;
}
public:
void DoWork()
{
m_c1->calcular();
m_v1->display();
m_m1->storage();
}
~Computer()
{
if (m_c1 != NULL)
{
delete m_c1;
m_c1 = NULL;
}
if (m_v1 != NULL)
{
delete m_c1;
m_v1 = NULL;
}
if(m_m1 != NULL)
{
delete m_c1;
m_m1 = NULL;
}
}
private:
CPU *m_c1;
VideoCard *m_v1;
Memory* m_m1;
};
void test01()
{
CPU* cpu = new LenovoCPU;
Memory* memo = new AppleMemory;
VideoCard* vd = new InterVideoCard;
Computer *cp = new Computer(cpu, vd, memo);
cp->DoWork();
delete cp;
}
int main()
{
test01();
}