17_多态
多态
静态多态(编译时多态, 早绑定): 函数重载, 运算符重载, 重定义
动态多态(运行时多态, 晚绑定): 虚函数
虚函数
父类指针 保存 子类空间地址 (带来的问题)
#include <iostream>
using namespace std;
class Animal
{
public:
void speak()
{
cout << "动物在说话" << endl;
}
};
class Dog: public Animal
{
public:
void speak()
{
cout << "狗在汪汪" << endl;
}
};
int main()
{
Animal *p = new Dog;
p->speak(); //动物在说话
return 0;
}
其实用户的需求: p->speak希望等到的是"狗在汪汪"而不是"动物在说话"。原因在此:
虚函数的定义
成员函数前jiavirtual修饰
#include <iostream>
using namespace std;
class Animal
{
public:
//虚函数
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
class Dog: public Animal
{
public:
//子类重写 父类的虚函数:函数名, 返回值类型, 参数类型个数顺序 必须完全一致
void speak() //virtual可加可不加 都是虚函数
{
cout << "狗在汪汪" << endl;
}
};
int main()
{
Animal *p = new Dog;
p->speak(); //狗在汪汪
return 0;
}
多态条件: 有继承, 子类重写父类的虚函数, 父类指针 指向子类空间
虚函数的动态绑定机制
#include <iostream>
using namespace std;
class Animal
{
public:
//虚函数
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
class Dog: public Animal
{
public:
void speak()
{
cout << "狗在汪汪" << endl;
}
};
class Cat: public Animal
{
public:
void speak()
{
cout << "猫在喵喵" << endl;
}
};
void animalSpeak(Animal *p)
{
p->speak();
}
int main()
{
Dog *dog = new Dog;
Cat *cat = new Cat;
animalSpeak(dog); //狗在汪汪
animalSpeak(cat); //猫在喵喵
return 0;
}
纯虚函数
如果基类一定派生处子类,而子类一定会重写父类的虚函数,那么父类的虚函数中的函数体是无意义,可不可以不写父类虚函数的函数体呢?可以的,那就必须了解纯虚函数。
纯虚函数的定义方式
class Animal
{
public:
//纯虚函数
virtual void speak() = 0;
};
1
一旦类中有纯虚函数,那么这个类 就是抽象类。
2
抽象类不能实例化对象。(Animal ob;错误)
3
抽象类 必须被继承 同时 子类 必须重写 父类的所有纯虚函数,否则 子类也是抽象类。
4
抽象类主要的目的 是设计 类的接口:
#include <iostream>
using namespace std;
//有纯虚函数的类: 抽象类
class Animal
{
public:
//纯虚函数
virtual void speak01() = 0;
virtual void speak02() = 0;
};
class Dog: public Animal
{
public:
//子类一定要重写父类所有的纯虚函数
void speak01()
{
cout << "Dog在汪汪" << endl;
}
void speak02(){}
};
int main()
{
// Animal ob; //error 抽象类不能实例化对象
Dog *dog = new Dog;
dog->speak01();
return 0;
}
抽象类主要的目的 是设计 类的接口:
虚函数和纯虚函数的区别
虚函数: virtual修饰 有函数体 不会导致父类为抽象类。
纯虚函数: virtual修饰, =0,没有函数体导致父类为抽象类。子类必须重写父类的所有纯虚函数。
虚析构函数
虚析构函数的定义
virtual修饰析构函数
目的: 通过父类指针 释放子类空间
#include <iostream>
using namespace std;
class Animal
{
public:
Animal()
{
cout << "Animal的无参构造" << endl;
}
virtual void speak(){}
//虚析构
virtual ~Animal()
{
cout << "Animal的析构函数" << endl;
}
};
class Dog: public Animal
{
public:
Dog()
{
cout << "Dog的无参构造" << endl;
}
void speak()
{
cout << "Dog在汪汪" << endl;
}
~Dog()
{
cout << "Dog的析构函数" << endl;
}
};
int main()
{
Animal *dog = new Dog;
dog->speak();
//通过父类指针, 释放子类的所有空间
delete dog;
return 0;
}
纯虚析构函数的定义
纯虚析构的本质:是析构函数,各个类的回收工作。而且析构函数不能被继承。
必须为纯虚析构函数提供一个函数体。
纯虚析构函数 必须在类外实现.
#include <iostream>
using namespace std;
class Animal
{
public:
//纯虚函数
virtual void speak() = 0;
//纯虚析构函数 必须在类外实现
virtual ~Animal() = 0;
};
class Dog: public Animal
{
public:
void speak()
{
cout << "狗汪汪" << endl;
}
~Dog()
{
cout << "Dog析构函数" << endl;
}
};
Animal::~Animal()
{
cout << "Animal的析构函数" << endl;
}
int main()
{
Animal *p = new Dog;
p->speak();
delete p;
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析