情况一: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;
}
输出结果:
![](https://img-my.csdn.net/uploads/201204/10/1334038892_6848.png)
在有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;
}
输出结果:
![](https://img-my.csdn.net/uploads/201204/10/1334039736_5183.png)
这种情况只是单纯的指针指向的地址不同而已~