(持续更新)c++中的继承、封装、多态

c++面向对象的三大特性为:继承、封装和多态

c++认为万事万物都皆为对象,对象上有其属性和行为

例如:

  人可以作为对象,属性有姓名、年龄、身高、体重…,行为有走、跑、跳、吃饭、唱歌⋯

  车也可以作为对象,属性有轮胎、方向盘、车灯…行为有载人、放音乐、放空调…

  具有相同性质的对象,我们可以抽象称为类,人属于人类,车厲于车类

 

1.封装

1.1封装的意义

封装是c++面向对象的三大特性之一

封装的意义:

  • 将属性和行为作为一个整体,表现生活中的事物
  • 将属性和行为加以权限控制

封装意义一:

在设计类的时候,属性和行为写在一起,表现事物。

语法:class 类名{ 访问权限:属性 / 行为 };

实例代码:

#include <iostream>

using namespace std;

const double PI = 3.14;

class Circle {
public:
    int m_r;

    double calculate_ZC() {
        return 2 * PI * m_r;
    }
};

int main() {
    //实例化:通过一个类,创建一个对象的过程
    Circle c1;
    c1.m_r = 10;
    cout << "圆的周长为:" << c1.calculate_ZC() << endl;
    return 0;
}

 

封装意义二:

类在设计时,可以把属性和行为放在不同的权限下,加以控制

类中的属性和行为,我们统一称为成员:

属性——成员属性、成员变量

行为——成员函数、成员方法

访问权限有三种:

(1)public 公共权限

(2)protected 保护权限

(3)private 私有权限

实例代码:

#include <iostream>
#include <string>

using namespace std;

class Student {
    //属性
public:
    string m_name;
    int m_age;
    //行为
public:
    void setName(string name) {
        m_name = name;
    }

    void setAge(int age) {
        m_age = age;
    }

    void showStu() {
        cout << "学生姓名:" << m_name << endl << "学生年龄:" << m_age << endl;
    }
};

int main() {
    Student s1;
    s1.setName("张三");
    s1.setAge(18);
    s1.showStu();
}

 

1.2struct和class的区别

c++中struct和class唯一的区别就在于默认的访问权限不同

区别:

  • struct默认权限为公共
  • class默认权限为私有

 

1.3成员属性设置为私有

优点一:将所有成员属性设置为私有,可以自己控制读写权限

优点二:对于写权限,我们可以检测数据的有效性

实例代码:

#include<iostream>
#include<string>

using namespace std;

class Person {
private:
    string m_name; //姓名 可读可写
    int m_age = 18; //年龄 只读
    string m_addr; //地址 只写

public:
    void setName(string name) {
        m_name = name;
    }

    string getName() {
        return m_name;
    }

    int getAge() {
        return m_age;
    }

    void setAddr(string addr) {
        m_addr = addr;
    }

private:
    void showStu() {
        cout << "姓名:" << m_name << "年龄:" << m_age << endl;
    }
};

int main() {
    Person p1;
    p1.setName("张三");
    cout << "姓名:" << p1.getName() << endl;
    cout << "年龄:" << p1.getAge() << endl;
}

 

 

2.继承

2.1继承的意义

继承是c++面向对象的三大特性之一

子类继承父类

继承的好处:可以减少重复的代码

如:

class B:public class A;

A类称为 父类 或 基类

B类称为 子类 或派生类

派生类中的成员包含两大部分:

一类是从基类继承过来的,一类是自己增加的成员;

从基类继承过来的表现其共性,而新增的成员体现了其个性。

 

2.2继承的方式

继承的语法:class 子类 : 继承方式 父类

继承一共有三种:

  • 公共继承
  • 保护继承
  • 私有继承

图示:

总结:

父类中的公共权限的成员,到子类中依然是公共权限;

父类中的保护权限的成员,到子类中依然是保护权限;

父类中的私有权限的成员,子类访问不到。

 

 

3.多态

3.1多态的意义

多态是c++面向对象的三大特性之一

多态分为两类:

  • 静态多态:函数重载和运算符重载属于静态多态,复用函数名
  • 动态多态:派生类和虚函数实现运行时多态

静态多态和动态多态的区别:

  • 静态多态的函数地址早绑定:编译阶段确定函数地址
  • 动态多态的函数地址晚绑定:运行阶段确定函数地址

 

实例代码1:

#include <iostream>

using namespace std;

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;
    }
};

//执行说话的函数
void doSpeak(Animal *animal) {
    animal->speak();
}

void test01() {
    //栈区开辟内存
    Cat cat;
    doSpeak(&cat);
    Dog dog;
    doSpeak(&dog);
}

int main() {
    test01();
}

运行结果:

小猫在说话

小狗在说话

 

3.2纯虚函数和抽象类

在多态中,通常父类的虚函数的实现是毫无意义的,主要都是调用子类重写的内容。

因此可以将虚函数改为纯虚函数。

纯虚函数语法:virtual 返回值类型 函数名(参数列表)=0;

当类中有了纯虚函数,这个类也称为抽象类。

抽象类的特点:

  • 无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则该子类也属于抽象类

 

实例代码2:

#include <iostream>

using namespace std;

class abstractCaculator {
public:
    //纯虚函数
    virtual int getResult() = 0;

    int m_Num1;
    int m_Num2;
};

//加法计算器
class addCalculator : public abstractCaculator {
public:
    int getResult() {
        return m_Num1 + m_Num2;
    }
};

//减法计算器
class subCalculator : public abstractCaculator {
public:
    int getResult() {
        return m_Num1 - m_Num2;
    }
};

//乘法计算器
class mulCalculator : public abstractCaculator {
public:
    int getResult() {
        return m_Num1 * m_Num2;
    }
};

void test01() {
    //堆区开辟内存
    abstractCaculator *abs = new addCalculator;
    abs->m_Num1 = 100;
    abs->m_Num2 = 200;
    cout << abs->m_Num1 << "+" << abs->m_Num2 << "=" << abs->getResult() << endl;
    delete abs;

    abs = new subCalculator;
    abs->m_Num1 = 300;
    abs->m_Num2 = 200;
    cout << abs->m_Num1 << "-" << abs->m_Num2 << "=" << abs->getResult() << endl;
}

int main() {
    test01();
}

运行结果:

100+200=300

300-200=100

 

实例代码3:

#include <iostream>

using namespace std;

class abstractDrink {
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 abstractDrink {
public:
    //重写基类中的纯虚函数
    void Boil() {
        cout << "煮水" << endl;
    }

    void Brew() {
        cout << "冲泡咖啡" << endl;
    }

    void PourInCup() {
        cout << "倒入杯中" << endl;
    }

    void PutSomething() {
        cout << "加入糖和牛奶" << endl;
    }
};

class Tea : public abstractDrink {
public:
    void Boil() {
        cout << "煮水" << endl;
    }

    void Brew() {
        cout << "冲泡茶叶" << endl;
    }

    void PourInCup() {
        cout << "倒入杯中" << endl;
    }

    void PutSomething() {
        cout << "加入柠檬" << endl;
    }
};


void makeDrink(abstractDrink *abs) {
    abs->makeDrink();
}

void test01() {
    //栈区开辟内存
    Coffee cf;
    makeDrink(&cf);
    Tea t;
    makeDrink(&t);
}

int main() {
    test01();
}

 

posted @ 2024-03-07 13:43  バカなの  阅读(9)  评论(0编辑  收藏  举报