C++类与对象--7 特性三:多态

发布于:2025-05-21 ⋅ 阅读:(20) ⋅ 点赞:(0)

7.1 多态的实现

(1)静态多态

  • 函数重载运算符重载
  • 编译阶段确定函数地址

(2)动态多态

  • 派生类(继承关系)虚函数(派生类重写)实现动态多态
  • 运行阶段确定函数地址
  • 使用:父类的引用指针指向子类对象
class Animal
{
public:
    virtual void speek() // 虚函数
    { std::cout << "dongwu speek." << std::endl; }
};
​
class Cat:public Animal
{
public:
    void speek() // 对父类虚函数的重写
    { std::cout << "cat speek." << std::endl; }
};
​
class Dog:public Animal
{
public:
    void speek() // 对父类虚函数的重写
    { std::cout << "dog speek." << std::endl; }
};
​
void doSpesk(Animal & animal) // 父类的引用作为函数形参
{ animal.speek(); }
​
int main()
{
    Cat cat;
    doSpesk(cat); // 父类的引用指向子类的对象
    Dog dog;
    doSpesk(dog); // 父类的引用指向子类的对象
​
    return 0;
}

7.2 多态的底层原理

class Animal
{
public:
    virtual void speek() // 虚函数
    { std::cout << "dongwu speek." << std::endl; }
};
  • Animal类内部speek函数不加virtual时,Animal类大小为1字节(空对象)
  • Animal类内部speek函数加virtual后,Animal类大小为3字节(多了一个虚拟函数指针vfptr)

7.3 纯虚函数和抽象类

  • 多态中,父类中实现的虚函数不会被使用,主要使用的是子类中重写的函数
  • 将父类中的虚函数写成纯虚函数,父类变成抽象类
  • 抽象类特点如下:
  1. 不能实例化对象
  2. 子类必须重写纯虚函数,否则子类也自动变成抽象类
class Base
{ 
    virtual void func() = 0; // 纯虚函数语法
};
​
class Son:public Base
{void func(){}}; // 子类重写纯虚函数
​
int main()
{
    Base * son = new Son; // 父类指针指向子类,实现多态
    son->func();
}

7.4 虚析构和纯虚析构

  • 多态中,子类如果开辟了堆区内存,父类指针将无法调用到子类析构函数去释放堆区内存
  • 虚析构函数纯虚析构函数可以解决上述问题
  • 虚析构函数和纯虚析构函数除了声明,还需要定义(用于父类堆区数据释放)
  • 声明纯虚析构函数的类,变成抽象类
class Base
{
public:
    virtual ~Base() = 0; // 纯虚析构的声明
};
​
Base::~Base(){} // 纯虚析构的定义实现(必须有,用于堆区数据释放)
​
class Son:public Base
{
public:
    Son(int val){m_val = new int(val);} // 堆区分配内存
    ~Son()
    {
        if(m_val != NULL)
        {
            delete m_val;
            m_val = NULL;
        }
    }
    
    int * m_val;
};
​
int main()
{
    Base * son = new Son(10); // 父类指针指向子类对象
    delete son; // 调用子类析构函数释放堆区内存
    
    system("pause");
    return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到