最近看了下C++虚函数的相关知识,现在想自己编写代码运行一下,可能在面试的时候有点小帮助,都是些基础的不能再基础的了
如下是基类与派生类的定义代码,接下来的执行结果的分析,都是以此为依据:
1 class Base { 2 public: 3 Base() {cout << "Base constructor" << endl;} 4 ~Base() {cout << "Base destructor" << endl;} 5 virtual void f(void) {cout << "Base::f" << endl;} 6 virtual void g(void) {cout << "Base::g" << endl;} 7 virtual void h(void) {cout << "Base::h" << endl;} 8 }; 9 10 class Derived : public Base { 11 public: 12 Derived(){ cout << "Derived constructor" << endl;} 13 ~Derived() {cout << "Derived destructor" << endl;} 14 virtual void f() {cout << "Derived::f" << endl;} 15 virtual void g1() {cout << "Derived::g1" << endl;} 16 virtual void h1() {cout << "Derived::h1" << endl;} 17 };
1、如果main函数是如下编写:
1 int main() { 2 Base *b; 3 Derived *d; 4 return 0; 5 }
此时不会调用类中的构造函数,即不会任何输出(如图1所示)。说明,光是定义了类指针,并不会创建一个类的实例
图1
2、如果main函数如下编写:
1 int main() { 2 Base *b = new Derived; 3 return 0; 4 }则结果会如图2所示,但是为什么程序执行完,却不执行Base类的析构函数?我自己认为,new是分配堆区内存,而堆区是不能自动执行销毁的,必须自己手动销毁,所以这里不会输出Base类中析构函数的执行语句;如果要想输出Base类中析构函数的执行语句,必须要加 delete b; b = NULL; 才可以实现,如图3;说到这里,我有个疑问,为什么图3中没有输出派生类Derived中的析构函数语句“Derived destructor”???请各位大神指教一下,我也是个菜鸟
图2
图3(注意,main函数里面多加了两句代码)
图4(注意代码的修改)
注:上面的图2,3,4 都是我一时兴起编出来的,主要是面试的时候可以用到,并且可以帮助自己理解,下面才开始正式的虚函数调用
3、虚函数的调用
1 int main() { 2 Base *b = new Derived; 3 b->f(); //这里先在子类中找,如果有,调用子类的;如果没有,到父类中找;如果都没有找到virtua1函数f,则报错 4 b->g(); //调用父类,因为子类并没有覆盖父类的虚函数 5 b->h(); //同上 6 delete b; 7 b = NULL; 8 return 0; 9 }
这里的指针b,只能调用到父类中的virtua1函数和子类中覆盖父类的同名virtua1函数,也就是说,指针b在这里并不能调用到子类函数中g1和h1两个虚函数
运行结果如图5;
图5
图6(区别就是没有手动分配内存,这里函数调用的情况和图5一样)
图7(只是多加了子类对象d的相关调用)