情况一:B继承A,有同名函数,基类中的函数不为虚函数
#include <iostream> using namespace std; class A { public: A() { a = 1;b = 2; } ~A() {} void fun() { printf("%d %d\n",a,b); cout<<"A fun;"<<endl; } int a; int b; }; class B: public A { public: B() { c = 3;} ~B() {} void fun() { printf("%d\n",c); cout<<"B fun;"<<endl; } int c; }; int _tmain(int argc, _TCHAR* argv[]) { A oba; B *pb = (B*)(&oba); pb->fun(); B obj; A *pa = (A*)(&obj); pa->fun(); system("pause"); return 0; }
输出结果:
在没有virtual的情况下,虚函数表中没有相应函数,则直接调用当前类型的相应函数,只是指向的地址有变化。
printf("%d\n",c);这句话输出的结果不定,是因为只调用了A的构造函数,没有调用B的构造函数,从而c没有初值的原因。
而printf("%d %d\n",a,b);是因为在创建B对象obj的时候调用了A、B的构造函数,使得a,b,c都有了初值,所以能正确输出结果~~~
情况二:B继承A,有同名函数,基类中的函数为虚函数
// 11.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> using namespace std; class A { public: A() { a = 1;b = 2; } ~A() {} virtual void fun() { printf("%d %d\n",a,b); cout<<"A fun;"<<endl; } int a; int b; }; class B: public A { public: B() { c = 3;} ~B() {} void fun() { printf("%d\n",c); cout<<"B fun;"<<endl; } int c; }; int _tmain(int argc, _TCHAR* argv[]) { A oba; B *pb = (B*)(&oba); pb->fun(); B obj; A *pa = (A*)(&obj); pa->fun(); system("pause"); return 0; }
输出结果:
在有virtual的情况下:
基类的对象实例是不存在虚函数表覆盖的,所以在查询函数时会查询到基类的函数。
派生类的对象实例的虚函数表中的函数会覆盖其中的同名函数,故会查询到派生类函数(也就是多态)。
B *pb是个指针,所以这并没有生产对象,只是分配了一个指向B类对象的指针。
B obj;
A *pa = (A*)(&obj);
pa->fun();
虚表指针是依附于对象存在的,这里只构造了B的对象obj,这句表达式只是一个模型转换,不涉及到A类对象的构造,所以pa指向的空间类的虚表指针依然是B类的虚表指针,指向的自然是B类的虚函数。
情况三:B不继承A,有同名函数
#include "stdafx.h" #include <iostream> using namespace std; class A { public: A() { a = 1;b = 2; } ~A() {} void fun() { printf("%d %d\n",a,b); cout<<"A fun;"<<endl; } int a; int b; }; class B { public: B() { c = 3;} ~B() {} void fun() { printf("%d\n",c); cout<<"B fun;"<<endl; } int c; }; int _tmain(int argc, _TCHAR* argv[]) { A oba; B *pb = (B*)(&oba); pb->fun(); B obj; A *pa = (A*)(&obj); pa->fun(); system("pause"); return 0; }
输出结果:
这种情况只是单纯的指针指向的地址不同而已~