C++学习 --- 类和对象之多态

七、多态
1、多态的基本的概念

#include <iostream>
#include <string>
using namespace std;
//多态
//动态多态满足条件
//1.有继承关系
//2.子类重写父类的虚函数 
//重写:函数返回值类型,函数名,参数列表完全相同
//动态多态的使用
//父类的指针或者引用指向子类传入的对象
class Animal {
public:
    //虚函数
    virtual void speak()
    {
        cout << "动物在说话" << endl;
    }
};
​
class Cat :public Animal {
public:
    void speak() {
        cout << "小猫在说话" << endl;
    }
};
​
class Dog: public Animal {
public:
    void speak() {
        cout << "小狗在说话" << endl;
    }
};
​
//执行说话的函数
//Animal 的引用接受子类的对象
//Animal &animal = cat;
//地址早绑定,在编译阶段确定函数地址
//如果想执行猫说话,那个这个地址就不能提前绑定,
//需要在运行阶段绑定,地址晚绑定,在Animal类的speak前加关键字virtual
void doSpeak(Animal &animal) {
    animal.speak();
}
​
void test01() {
    Cat cat;
    Dog dog;
    doSpeak(cat);
    doSpeak(dog);
}
​
//4个字节
void test02() {
    cout << "sizeof Animal = " << sizeof(Animal) << endl;
}
​
int main(){
    test01();
    test02();
​
    system("pause");
    return 0;
}

 

父类Animal:

子类Cat 没有发生重写:

子类Cat 重写后:

 

2、多态案例一 计算器类

#include <iostream>
#include <string>
using namespace std;
​
//分别利用普通的写法和多态技术实现计算器
//普通写法
class Calculator {
public:
    int getResult(string oper) {
        if (oper == "+") {
            return m_Num1 + m_Num2;
        }
        if (oper == "-") {
            return m_Num1 - m_Num2;
        }
        if (oper == "*") {
            return m_Num1 * m_Num2;
        }
        if (oper == "/") {
            return m_Num1 / m_Num2;
        }
        //如果想扩展新的功能,需要修改源码
        //在真实的开发中,开闭原则
        //开闭原则:对扩展进行开放,对修改进行关闭
    }
​
    int m_Num1;   //操作数1
    int m_Num2;   //操作数2
};
​
void test01() {
    //创建计算器对象
    Calculator c;
    c.m_Num1 = 10;
    c.m_Num2 = 10;
    cout << c.m_Num1 << "+" << c.m_Num2 << " = " << c.getResult("+") << endl;
    cout << c.m_Num1 << "-" << c.m_Num2 << " = " << c.getResult("-") << endl;
    cout << c.m_Num1 << "*" << c.m_Num2 << " = " << c.getResult("*") << endl;
    cout << c.m_Num1 << "/" << c.m_Num2 << " = " << c.getResult("/") << endl;
}
​
​
//利用多态实现计算器
//实现计算器的抽象类
class AbstractCalculator {
public:
    virtual int getResult() {
        return 0;
    }
    int m_Num1;  //操作数1
    int m_Num2;  //操作数2
};
​
//加法计算器类
class AddCalculator : public AbstractCalculator {
public:
    int getResult() {
        return m_Num1 + m_Num2;
    }
};
​
//减法计算器类
class SubCalculator : public AbstractCalculator {
public:
    int getResult() {
        return m_Num1 - m_Num2;
    }
};
​
//乘法计算器类
class MulCalculator : public AbstractCalculator {
public:
    int getResult() {
        return m_Num1 * m_Num2;
    }
};
​
void test02() {
    //多态使用条件
    //父类指针或者引用指向子类对象
    AbstractCalculator * abc = new AddCalculator;
    abc->m_Num1 = 10;
    abc->m_Num2 = 10;
    cout << abc->m_Num1 << "+" << abc->m_Num2 << " = " << abc->getResult() << endl;
    //使用完销毁指针堆区的数据
    delete abc;
​
    abc = new SubCalculator;
    abc->m_Num1 = 100;
    abc->m_Num2 = 100;
    cout << abc->m_Num1 << "-" << abc->m_Num2 << " = " << abc->getResult() << endl;
    delete abc;
​
    abc = new MulCalculator;
    abc->m_Num1 = 10;
    abc->m_Num2 = 100;
    cout << abc->m_Num1 << "*" << abc->m_Num2 << " = " << abc->getResult() << endl;
    delete abc;
}
​
//多态带来的好处
//1.组织结构清晰
//2.可读性强
//3.对于前期和后期扩展及维护性高
int main(){
test01();
test02();

system("pause");
return 0;
}

 

3、纯虚函数和抽象类

#include <iostream>
#include <string>
using namespace std;
​
//纯虚函数和抽象类
class Base {
public:
    //纯虚函数
    virtual void func() = 0;
    //只要有一个纯虚函数,这个类称为抽象类
    //抽象类特点:
    //1.无法实例化对象
    //2.抽象类的子类,必须要重写父类中的纯虚函数,否则也属于抽象类
};
​
class Son1 :public Base {
public :
​
};
​
class Son2 :public Base {
public:
    void func() {
        cout << "func 函数调用" << endl;
    }
};
​
void test01() {
    //抽象类无法实例化对象
    //Base b;
    //new Base;
    //子类未重写父类中的纯虚函数,属于抽象类,抽象类无法实例化对象
    //Son1 s;
//多态,使接口更通用化,通过同一个父类指针,由于指向的对象的不同,可以调用多种状态的函数。
    Base * base = new Son2;
    base->func();
    delete base;
}
​
int main(){
    test01();
    
    system("pause");
    return 0;
}

 

4、多态案例二 制作饮品

#include <iostream>
#include <string>
using namespace std;
​
//多态的案例2 制作饮品
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 {
    //煮水
    virtual void Boil() {
        cout << "煮农夫山泉水" << endl;
    }
    //冲泡
    virtual void Brew() {
        cout << "冲泡咖啡" << endl;
    }
    //倒入杯中
    virtual void PourInCup() {
        cout << "倒入咖啡杯中" << endl;
    }
    //加入辅料
    virtual void PutSomething() {
        cout << "加入糖和牛奶" << endl;
    }
};
​
​
//制作茶叶
class Tea :public AbstractDrinking {
    //煮水
    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 test01() {
    //制作咖啡
    doWork(new Coffee);
    cout << "-------------------" << endl;
    //制作茶
    doWork(new Tea);
}
​
int main(){
    test01();
    
    system("pause");
    return 0;
}

 

5、虚析构和纯虚析构

#include <iostream>
#include <string>
using namespace std;
​
//虚析构和纯虚析构
class Animal {
public:
    Animal() {
        cout << "Animal 构造函数调用" << endl;
    }
    //纯虚函数
    virtual void speak() = 0;
​
    //析构改为虚析构,会走子类中的代码
    //利用虚析构可以解决,父类指针释放子类对象时堆区释放不完整的问题
    /*virtual ~Animal() {
        cout << "Animal 析构函数调用" << endl;
    }*///纯虚析构
    //纯虚析构和虚析构只能有一个
    //纯虚析构需要声明也需要实现,若无实现:在链接阶段出现 “无法解析的外部符号LNK2019”
    //有个纯虚析构之后,这个类也属于抽象类,无法实例化对象。
    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() {
        if (m_Name != NULL) {
            cout << "Cat 的析构函数调用" << endl;
            delete m_Name;
            m_Name = NULL;
        }
    }
    string * m_Name;
};
​
void test01() {
    Animal * animal = new Cat("Tom");
    animal->speak();
    delete animal;
    //父类指针在析构时 不会调用子类中析构函数,导致子类如果有堆区属性,会出现内存泄露
    //利用虚析构可以解决,父类指针释放子类对象时堆区释放不完整的问题
}   
​
int main(){
    test01();
    
    system("pause");
    return 0;
}

 

6、多态案例三 电脑组装

#include <iostream>
#include <string>
using namespace std;
​
//抽象出不同零件类
//抽象cpu类
class CPU {
public:
    //抽象的计算函数
    virtual void calculate() = 0;
};
​
//抽象显卡类
class VideoCard {
public:
    //抽象的显示函数
    virtual void display() = 0;
};
​
//抽象内存类
class Memory {
public:
    //抽象的存储函数
    virtual void storage() = 0;
};
​
//电脑类
class Computer {
public:
    Computer(CPU *cpu, VideoCard *vc, Memory * mem) {
        m_cpu = cpu;
        m_vc = vc;
        m_mem = mem;
    }
​
    ~Computer() {
        //释放cpu零件
        if (m_cpu != NULL) {
            delete m_cpu;
            m_cpu = NULL;
        }
        //释放显卡零件
        if (m_vc != NULL) {
            delete m_vc;
            m_vc = NULL;
        }
        //释放内存零件
        if (m_mem != NULL) {
            delete m_mem;
            m_mem = NULL;
        }
    }
​
    //提供工作的函数
    void work() {
        m_cpu->calculate();
        m_vc->display();
        m_mem->storage();
    }
​
private:
    CPU * m_cpu;        //cpu的零件指针
    VideoCard * m_vc;   //显卡的零件指针
    Memory *m_mem;      //内存的零件指针
};
​
//具体的厂商
//Intel厂商
class IntelCPU :public CPU {
public:
    virtual void calculate() {
        cout << "Intel 的cpu开始 计算了!" << endl;
    }
};
​
class IntelVideoCard :public VideoCard {
public:
    virtual void display() {
        cout << "Intel 的显卡开始 显示了!" << endl;
    }
};
​
class IntelMemory :public Memory {
public:
    virtual void storage() {
        cout << "Intel 的内存条开始 存储了!" << endl;
    }
};
​
//Lenovo厂商
class LenovoCPU :public CPU {
public:
    virtual void calculate() {
        cout << "Lenovo 的cpu开始 计算了!" << endl;
    }
};
​
class LenovoVideoCard :public VideoCard {
public:
    virtual void display() {
        cout << "Lenovo 的显卡开始 显示了!" << endl;
    }
};
​
class LenovoMemory :public Memory {
public:
    virtual void storage() {
        cout << "Lenovo 的内存条开始 存储了!" << endl;
    }
};
​
void test01() {
    //第一台电脑零件
    CPU * intelCPU = new IntelCPU;
    VideoCard *intelCard = new IntelVideoCard;
    Memory * intelMem = new IntelMemory;
​
    //创建第一台电脑
    cout << "第一台电脑开始工作:" << endl;
    Computer * computer1 = new Computer(intelCPU, intelCard, intelMem);
    computer1->work();
    delete computer1;
​
    //第二台电脑组装
    cout << "--------------" << endl;
    cout << "第二台电脑开始工作:" << endl;
    Computer * computer2 = new Computer(new LenovoCPU, new LenovoVideoCard, new LenovoMemory);
computer2->work();
delete computer2;
​
//第三台电脑组装
cout << "--------------" << endl;
cout << "第三台电脑开始工作:" << endl;
Computer * computer3 = new Computer(new LenovoCPU, new IntelVideoCard, new LenovoMemory);
computer3->work();
delete computer3;
}
​
int main(){
test01();
system("pause");
return 0;
}

 

 

posted @ 2021-08-23 21:41  yiwenzhang  阅读(107)  评论(0编辑  收藏  举报