本文共 3029 字,大约阅读时间需要 10 分钟。
静态多态:函数重载
动态多态:函数重写 virtual关键字 静态联编:地址早绑定,编译阶段绑定好地址 动态联编:在运行阶段确定函数地址 多态:父类的引用或者指针指向子类对象 原理:对于一个只有成员函数的类 其大小为1 如果给成员函数添加virtual关键字,则大小变为4,这是由于该类内部出现一个指针 vfptr 虚函数表指针,指向虚函数表中储存的指向该类内的成员函数的地址,如果该子类没有声明与父类virtual函数相同的同名函数,或者声明了与父类中没加virtual的同名函数,构造函数中,子类的vfptr会拥有与父类的虚函数表相同的虚函数表 指向&Animal::speak,有子类继承该父类时,如果使用与父类中virtual声明的同名函数,叫做重写,重写必须返回值 参数 类型 顺序都相同 ,子类会将自己虚函数表中的父类函数地址改为自己的函数地址,vfptr会指向子类自己的虚函数表中该函数的地址 &Cat::speak()Animal *animal = new Cat;
animal.speak(); 父类指针指向子类对象 调用子类重写后的函数class Animal{ public: virtual void speak() { cout<<"Animal Speak"<
真正的开发中,有个原则:开闭原则。
对扩展开放,对修改关闭。 使用多态 利于后期扩展 结构性好 可读性高 但是效率会变低 结构变复杂。 利用多态 在需要加入新的功能时,只需要添加相应的类即可。普通虚函数:类内声明,类内实现,子类可以选择实现或者不实现。
纯虚函数:只声明,不实现,子类必须实现
如果父类有纯虚函数 子类中必须实现纯虚函数,否则该子类也是个抽象类(不能实例化对象)
如果父类有纯虚函数,该父类不能实例化对象 这个类有了纯虚函数,通常称为抽象类。class abstractCalculator{ public: void setval1(int a) { this->val1 = a; } void setval2(int b) { this->val2 = b; }// //虚函数// virtual int getResult()// { // return 0;// } //如果父类有纯虚函数 子类中必须实现纯虚函数,否则该子类也是个抽象类(不能实例化对象) //如果父类有纯虚函数,该父类不能实例化对象 //这个类有了纯虚函数,通常称为抽象类。 virtual int getResult() = 0; int val1; int val2;};class PulsCalculator:public abstractCalculator{ public: virtual int getResult() { return val1 + val2; }};class SubCalculator:public abstractCalculator{ public: virtual int getResult() { return val1 - val2; }};class subclass :public abstractCalculator{ public: int getResult() { return 0; }};void test003(){ abstractCalculator* puls = new PulsCalculator; puls->setval1(10); puls->setval2(20); cout<getResult()< setval1(10); puls->setval2(20); cout< getResult()<
普通析构是不会调用子类的析构的,所以在使用父类指针指向子类对象时,释放时,可能导致子类释放不干净。
class Animal1{ public: virtual void speak() { cout<<"animal speak"<m_Name = new char[strlen(name)+1]; strcpy(this->m_Name,name); } ~Cat1() { cout<<"Cat1 xigou"< m_Name != NULL) { delete[] m_Name; this->m_Name = NULL; } } virtual void speak() { cout<<"cat speak"< speak(); //查看调用了哪个析构 delete animal; //打印: Animal1 xigou //父类不使用虚析构时,调用了Animal1类的析构函数,不会调用子类的析构函数,和普通函数相同,所以需要父类使用虚析构函数}
纯虚析构需要类内声明,类外实现
出现纯虚析构函数,该类也是抽象类,不可实例化 子类虚构函数必须实现,否则也是抽象类 使用父类指针指向子类对象时,如果父类使用纯虚析构函数,则在释放时,先析构子类,再析构父类。//纯虚析构class Animal2{ public: virtual void speak() { cout<<"animal speak"<m_Name = new char[strlen(name)+1]; strcpy(this->m_Name,name); } ~Cat2() { cout<<"Cat1 xigou"< m_Name != NULL) { delete[] m_Name; this->m_Name = NULL; } } virtual void speak() { cout<<"cat speak"< speak(); //查看调用了哪个析构 delete animal; // 打印:Cat1 xigou Animal2 Pure virtual destructor //先析构子类,再析构父类}
转载地址:http://dssqf.baihongyu.com/