第十三章 虚函数
1. 指向对象的指针
常用father *pfather=new son;
不常用son *pson=new son;?????????
2. 虚函数
覆盖 体现虚函数的多态性(动态联编)
基类指针存储不同对象调用不同类的函数
5. 在编译时的静态联编
6. 在运行时的静态联编
7. 在运行时的动态联编(耗时)
动态联编体现了多态性 所以一定要有virtual 而且要用指针或者别名 否则不能实现
8. 在编译时的动态联编
9. 三种调用虚函数的方式比较
要想显示virtual
①存储不同对象的指针调用不同类的函数
②声明: 调用: 第一个按对象传递调用 不能呈现多态性。 按指针或引用传递 能呈现多态性
10. 系统是如何调用虚函数的
11. 在虚函数中使用成员名限定
在虚函数中使用成员名限定可以强行解除动态联编
12. 构造函数和虚析构函数
如果基类中定义了虚函数,那么也要有虚析构函数。这样对内存的回收就会更准确些(一般都在基类加virtual)
没有虚构造函数
13. 纯虚函数
纯虚函数就是基类只定义了函数体,没有实现过程,定义方法如: virtual void Eat() = 0; 不要 在cpp中定义;纯虚函数相当于接口,不能直接实例化,需要派生类来实现函数定义;
带纯虚函数的类叫虚基类,这种基类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。这样的类也叫抽象类。
虚函数是为了继承接口和默认行为
纯虚函数只是继承接口,行为必须重新定义
本章总结:
1. 动态联编(速度慢)(运行后才能确定指针指向那个对象) 静态联编(速度快)(编译后就能确定指针指向那个对象)
2. 只有基类virtual、父类指针、不同new类 的连用才能体现多态性
3. 成员名限定符可以强制解除动态联编p->Fahter::get();
4. 有虚函数,就要有虚析构函数(注意:只要看到派生类,不论有无虚函数,都要有虚析构函数)
5. 虚函数、虚析构函数virtual都设在基类
1 /** 2 运行时的动态联编 3 动态联编体现了多态性,一定要用virtual和指针,才能展示*******************① 4 */ 5 6 7 //#include"iostream" 8 //using namespace std; 9 //class Father 10 //{ 11 //public: 12 // Father(){cout<<"Father";} 13 // virtual int get(){return 1;} 14 // 15 //}; 16 //class Son:public Father 17 //{ 18 //public: 19 // Son(){cout<<"Son";} 20 // int get(){return 2;} 21 //}; 22 //int main() 23 //{ 24 // while(1) 25 // { 26 // bool x=false; 27 // Father *P; 28 // bool quit=false; 29 // do 30 // { 31 // x=false; 32 // cout<<"(1)父类(2)子类(3)退出:"; 33 // int choice; 34 // cin>>choice; 35 // 36 // switch(choice) 37 // { 38 // case 1:P=new Father; 39 // break; 40 // case 2:P=new Son; 41 // break; 42 // case 3:quit=true; 43 // break; 44 // default:cout<<"请输入进行选择: ";x=true; 45 // break; 46 // } 47 // }while(x==true); 48 // 49 // if(quit==true)//如果误写成quit=true那就直接运行了 50 // { 51 // break; 52 // } 53 // else 54 // { 55 // cout<<P->get()<<endl; 56 // delete P; 57 // P=NULL; 58 // } 59 // 60 // } 61 // 62 // return 0; 63 //} 64 65 66 67 68 //#include"iostream" 69 //using namespace std; 70 //class A 71 //{ 72 //public: 73 // virtual void one(){cout<<"one"<<endl;two();}; 74 // //此处一个virtual就可以了,因为以后的函数都有one间接调用************************② 75 // void two(){cout<<"two"<<endl;three();} 76 // void three(){cout<<"three"<<endl;four();} 77 // void four(){cout<<"three"<<endl;five();} 78 // void five(){cout<<"three"<<endl;} 79 //}; 80 //class B:public A 81 //{ 82 //public: 83 // void one(){cout<<"1"<<endl;two();}; 84 // void two(){cout<<"2"<<endl;three();} 85 // void three(){cout<<"3"<<endl;four();} 86 // void four(){cout<<"4"<<endl;five();} 87 // void five(){cout<<"5"<<endl;} 88 //}; 89 //class C:public A 90 //{ 91 //public: 92 // void one(){cout<<"一"<<endl;two();}; 93 // void two(){cout<<"二"<<endl;three();} 94 // void three(){cout<<"三"<<endl;four();} 95 // void four(){cout<<"四"<<endl;five();} 96 // void five(){cout<<"五"<<endl;} 97 //}; 98 //int main() 99 //{ 100 // A *p; 101 // int choice; 102 // bool quit=false; 103 // int x; 104 // while(1) 105 // { 106 // do 107 // { 108 // x=0; 109 // cout<<"(0)退出(1)英文(2)阿拉伯文(3)中文"<<endl; 110 // cin>>choice; 111 // switch(choice) 112 // { 113 // case 0:cout<<"退出程序"<<endl;quit=true; 114 // break; 115 // case 1:cout<<"英文:"<<endl;p=new A; 116 // break; 117 // case 2:cout<<"阿拉伯文:"<<endl;p=new B; 118 // break; 119 // case 3:cout<<"中文:"<<endl;p=new C; 120 // break; 121 // default:cout<<"请做出正确选择:"<<endl;x=1; 122 // } 123 // }while(x==1); 124 // if(quit) 125 // break; 126 // else 127 // { 128 // p->one(); 129 // //p->A::one();//成员限定符能强制解除动态联编 130 // delete p; 131 // p=NULL; 132 // } 133 // } 134 // return 0; 135 //} 136 137 138 139 140 //有virtual函数就要有virtual析构函数 141 #include"iostream" 142 using namespace std; 143 class A 144 { 145 public: 146 A(){cout<<"A类的构造函数"<<endl;}//构造函数没有虚函数****************③ 147 void fun(){cout<<"类A的fun()函数"<<endl;} 148 virtual ~A(){cout<<"A类的析构函数"<<endl<<endl;} 149 }; 150 class B:public A 151 { 152 public: 153 B(){cout<<"B类的构造函数"<<endl;} 154 void fun(){cout<<"类B的fun()函数"<<endl;} 155 ~B(){cout<<"B类的析构函数"<<endl;} 156 }; 157 int main() 158 { 159 A *pa=new A; 160 pa->fun(); 161 delete pa; 162 pa=NULL; 163 164 A *pb=new B;//用指向B类的A类指针调用重载函数,基类的析构函数要设为虚函数*********************④ 165 pb->fun(); 166 delete pb; 167 pb=NULL; 168 return 0; 169 }