1. //三大特征之一:继承
    2. //继承的好处:减少代码重复
    3. //语法:class 子类:public 父类
    4. //子类 也称 派生类
    5. //父类 也称 基类
    6. class P{
    7. public:
    8. int A;
    9. private:
    10. int B;
    11. };
    12. class P1:public P
    13. {
    14. public:
    15. int C;
    16. private:
    17. int D;
    18. };
    19. int main()
    20. {
    21. cout << "int 字节数:" << sizeof(int) << endl;//4
    22. cout << "P 字节数:" << sizeof(P) << endl;//8
    23. cout << "P1 字节数:(P1继承P)" << sizeof(P1) << endl;//16//父类中所有非静态成员属性都会被继承下去(包括私有)
    24. system("pause");
    25. return 0;
    26. }
    27. //子类和父类构造和析构的顺序
    28. class Base
    29. {
    30. public:
    31. Base(){
    32. cout << "Base的构造函数\n";
    33. }
    34. ~Base() {
    35. cout << "Base的析构函数\n";
    36. }
    37. };
    38. class Son:public Base
    39. {
    40. public:
    41. Son() {
    42. cout << "Son的构造函数\n";
    43. }
    44. ~Son() {
    45. cout << "Son的析构函数\n";
    46. }
    47. };
    48. int main()
    49. {
    50. Son P;
    51. //system("pause");
    52. return 0;
    53. /*Base的构造函数
    54. Son的构造函数
    55. Son的析构函数
    56. Base的析构函数*/
    57. }
    //子类和父类成员函数重名时。子类会隐藏父类中所有成员函数(函数重载),静态和非静态一样
    //访问子类成员:直接访问即可
    //访问父类成员:加作用域即可
    class Base {
    public:
        int m_A;//同名成员
        Base(){
            m_A = 100;
        }
        void func()//同名成员函数
        {
            cout << "Base成员函数调用!\n";
        }
    };
    class Son :public Base {
    public:
        int m_A;
        Son(){
            m_A = 200;
        }
        void func()//同名成员函数
        {
            cout << "Son成员函数调用!\n";
        }
    };
    int main()
    {
        Son S1;
        cout << S1.m_A << endl;//200
        //直接访问则访问的是子类成员,子类会隐藏父类中所有成员函数(函数重载)
        cout << S1.Base::m_A << endl;//100
        //子类对象加上作用域后访问父类成员(加作用域即可)
        cout << endl;
        S1.func();//Son成员函数调用!
        //直接访问则访问的是子类成员函数
        S1.Base::func();//Base成员函数调用!
        //子类对象加上作用域后访问父类成员函数(加作用域即可)
        cout << endl;
        Base B1;
        B1.func();//Base成员函数调用!
        //父类成员可直接调用
        return 0;
    }
    
    //语法:class 子类:继承方式 父类1,继承方式 父类2,.....
    //多继承中父类成员函数重名,则要加作用域区分
    
    class Base1 {
    public:
        int m_A;//重名
        int m_B;
        Base1() {
            m_A = 100;
            m_B = 200;
        }
    };
    class Base2 {
    public:
        int m_A;
        int m_C;
        Base2() {
            m_A = 100;
            m_C = 0;
        }
    };
    class Son :public Base1, public Base2//多继承
    {
    public:
        int M_A;
        Son()
        {
            M_A = 10;
        }
    };
    int main()
    {
        Son S;
        cout << S.Base1::m_A<<endl;//重名要加作用域
        cout << S.Base2::m_A << endl;
        cout << S.m_B << endl;//不用加作用域
        cout << "Son 所占字节数:" << sizeof(S)<<endl;
        system("pause");
        return 0;
    }
    
    //两个类继承一个类后被另一个类继承
    class Animal{
    public:
        int m_Age;
    };
    //利用虚基类解决菱形继承
    //使用关键字virtual,变为虚继承,此时Animal变为虚基类
    class Ship:virtual public Animal{};
    class Tuo :virtual public Animal{};
    class ShipTuo:public Ship, public Tuo{};
    int main()
    {
        ShipTuo S;
        //S.Ship::m_Age = 10;//需要加作用域
        //S.Tuo::m_Age = 20;
        //加入virtual后作用域将不再需要,m_Age共享同一个
        S.m_Age = 20;
        cout<<S.m_Age<<endl;
        return 0;
    }
    
    多态:
    多态分两大类:
        静态多态:函数重载 和 运算符重载属于静态多态,复用函数名
        动态多态:派生类和虚函数实现运行时多态
    静态多态和动态多态区别:
        静态多态的函数地址早绑定————编译阶段确定函数地址
        动态多态的函数地址玩绑定————运行阶段确定函数地址
    #include<iostream>
    #include<string>
    using namespace std;
    class Animal {
    public:
        virtual void Speak()//父类虚函数   //vfptr virtual function pointer 虚函数指针
        {
            cout << "动物在说话\n";
        }
    };
    class Cat:public Animal
    {
    public:
        void Speak()//子类对函数重写(函数返回值、函数名、形参列表、等等都必须一致)
        {
            cout << "小猫在说话\n";
        }
    };
    class Dog :public Animal
    {
    public:
        void Speak()//子类对函数重写
        {
            cout << "小狗在说话\n";
        }
    };
    动态多态满足条件
        1.有继承关系
        2.子类中对父类虚函数重写
    子类重写虚函数,替换父类继承到子类中的虚函数,父类虚函数依然存在
    
    多态使用
        父类的指针或者引用 指向子类对象(地址晚绑定)
    
    void doSpeak(Animal& animal)//Animal& animal=cat
    {
        animal.Speak();
    }
    int main()
    {
        Animal A;//父类函数依然存在
        doSpeak(A); //动物在说话
    
        Cat cat;
        doSpeak(cat);//小猫在说话
    
        Dog dog;
        doSpeak(dog);//小狗在说话
        system("pause");
        return 0;
    }
    
    #include<iostream>
    #include<string>
    using namespace std;
    
    //传统计算器
    class Calculator {
    public:
        int m_A;
        int m_B;
        int getResult(string ch);
    };
    int Calculator::getResult(string ch)
    {
        if (ch == "+")
            return m_A + m_B;
        else if (ch == "-")
            return m_A - m_B;
        else if (ch == "*")
            return m_A * m_B;
        //继续添加除法运算,则需要修改源代码!
        //引入多态
    }
    int main() {
        Calculator c;
        c.m_A = 10;
        c.m_B = 10;
        cout << c.m_A << "+" << c.m_B << "=" << c.getResult("+")<<endl;
        cout << c.m_A << "-" << c.m_B << "=" << c.getResult("-") << endl;
        cout << c.m_A << "*" << c.m_B << "=" << c.getResult("*") << endl;
    }
    
    //利用多态实现计算器
    //可读性强
    //组织结构清晰
    //对于前期和后期扩展以及维护性高
    
    class AbstractCaculator //实现计算器抽象类
    {
    public:
        int m_A;
        int m_B;
        AbstractCaculator() {
            m_A = 0;
            m_B = 0;
        }
        AbstractCaculator(int a,int b):m_A(a),m_B(b) {}
        virtual int getResult()
        {
            return 0;
        }
    };
    class Add:public AbstractCaculator
    {
    public:
        int getResult()
        {
            return m_A+m_B;
        }
    };
    class Sub :public AbstractCaculator
    {
    public:
        int getResult()
        {
            return m_A - m_B;
        }
    };
    class Mul :public AbstractCaculator
    {
    public:
        int getResult()
        {
            return m_A * m_B;
        }
    };
    int main()
    {
        //多态的使用条件
        //父类指针指向子类对象
        AbstractCaculator *abc=new Add;//父类指针指向子类对象
        abc->m_A = 10;
        abc->m_B = 10;
        cout << abc->m_A << "+" << abc->m_B << "=" << abc->getResult()<<endl;
        //delete abc;
    
        abc = new Sub;//父类指针指向子类对象
        abc->m_A = 10;
        abc->m_B = 10;
        cout << abc->m_A << "-" << abc->m_B << "=" << abc->getResult() << endl;
        delete abc;
    
        abc = new Mul;//父类指针指向子类对象
        abc->m_A = abc->m_B = 10;
        cout << abc->m_A << "*" << abc->m_B << "=" << abc->getResult() << endl;
        delete abc;
        return 0;
    }
    
    #include<iostream>
    #include<string>
    using namespace std;
    
    class Base//抽象类
    {
        纯虚函数
            只要有一个纯虚函数,这个类成为抽象类
        抽象类的特点
            1、无法实例化对象
            2、抽象类的子类必须(全部)重写父类中的纯虚函数,否则也是抽象类
            3、可以声明一个抽象类的指针和引用。通过指针或引用,可以指向并访问派生类对象,以访问派生类的成员
    public:
        virtual int func() = 0;
    };
    
    class Son1:public Base
    {
    public:
        int func()
        {
            cout << "Son1 func调用" << endl;
            return 0;
        }
    };
    class Son2 :public Base
    {
    public:
        int func()
        {
            cout << "Son2 func调用" << endl;
            return 0;
        }
    };
    int main()
    {
        //Base B;抽象类无法实例化对象
        Son1 S;
        S.func();
        //父类的指针或者引用指向子类对象(指向谁调用谁)
        Base* B = new Son1;
        B->func();//利用多态的技术调用
        delete B;
        B = new Son2;
        B->func();//利用多态的技术调用
        delete B;
        return 0;
    }
    
    #include<iostream>
    using namespace std;
    
    class Base
    {
    public://纯虚函数
        virtual void Boil()=0;//煮水
        virtual void Brew()=0;//冲泡
        virtual void PourInCup()=0;//倒入杯中
        virtual void PutSomething()=0;//加入辅料
    };
    class Tea :public Base
    {
    public:
        virtual void Boil()//煮水
        {
            cout << "水温100摄氏度!\n";
        }
        virtual void Brew()//冲泡
        {
            cout << "泡茶5分钟!\n";
        }
        virtual void PourInCup()//倒入杯中
        {
            cout << "倒入茶杯中\n";
        }
        virtual void PutSomething()//加入辅料
        {
            cout << "加入牛奶!\n";
        }
    };
    class Coffee :public Base
    {
    public:
        virtual void Boil()//煮水
        {
            cout << "水温100摄氏度!\n";
        }
        virtual void Brew()//冲泡
        {
            cout << "冲5分钟!\n";
        }
        virtual void PourInCup()//倒入杯中
        {
            cout << "倒入咖啡杯中\n";
        }
        virtual void PutSomething()//加入辅料
        {
            cout << "加入牛奶!\n";
        }
    };
    void doWork(Base* A)
    {
        A->Boil();
        A->Brew();
        A->PourInCup();
        A->PutSomething();
        delete A;//防止内存泄露
    }
    int main()
    {
        doWork(new Tea);
        cout << "------------------\n";
        doWork(new Coffee);
        return 0;
    }
    
    #include <iostream>
    using namespace std;
    #include <string>
    
    class Animal
    {
    protected:
        std::string m_name;
        // We're making this constructor protected because
        // we don't want people creating Animal objects directly,
        // but we still want derived classes to be able to use it.
        Animal(std::string name) : m_name(name){}
        // To prevent slicing (covered later)
        Animal(const Animal&) = default;
        Animal& operator=(const Animal&) = default;
    
    public:
        string getName() const
        {
            return m_name;
        }
        virtual string speak() const//加入virtual后输出想要的结果
        {
            return "???";
        }
    };
    class Cat : public Animal
    {
    public:
        Cat(string name) : Animal(name) {}
        string speak() const
        {
            return "Meow";
        }
    };
    class Dog : public Animal
    {
    public:
        Dog(string name) : Animal(name) { }
    
        string speak() const
        {
            return "Woof";
        }
    };
    
    int main()
    {
        const Cat cat("Fred");
        cout << "cat is named " << cat.getName() << ", and it says " << cat.speak() << '\n';
    
        const Dog dog("Garbo");
        cout << "dog is named " << dog.getName() << ", and it says " << dog.speak() << '\n';
    
        const Animal* pAnimal(&cat);//使用多态
        cout << "pAnimal is named " << pAnimal->getName() << ", and it says " << pAnimal->speak() << '\n';
    
        pAnimal = &dog;
        cout << "pAnimal is named " << pAnimal->getName() << ", and it says " << pAnimal->speak() << '\n';
    
        Animal* A = new Cat("Fred");
        cout << "cat is named " << A->getName() << ", and it says " << A->speak() << '\n';
        return 0;
    }