首先看代码,不采用虚函数的情况
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class A {
private:
int m_kk;
public:
A() {
m_kk = 100;
}
void print() {
cout << "this is A" << endl;
cout << m_kk << endl;
}
};
class B :public A {
public:
void print(){
cout << "this is B" << endl;
}
};
int main()
{
A a;
B b;
A* pa = &a;
A* pb = &b;
pa->print();
pb->print();
system("pause");
return 0;
}
上述的两次输出均为“this is A 100”。证明在不采用虚函数的基础上,用父类的指针指向子类,是指向子类中父类的一部分。其行为和父类相同。
下面是采用虚函数的情况
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class A {
private:
int m_kk;
public:
A() {
m_kk = 100;
}
virtual void print() {
cout << "this is A" << endl;
cout << m_kk << endl;
}
};
class B :public A {
public:
virtual void print(){
cout << "this is B" << endl;
}
};
int main()
{
A a;
B b;
A* pa = &a;
A* pb = &b;
pa->print();
pb->print();
system("pause");
return 0;
}
输出为this is A 100 this is B.证明父类指针指向子类对象时,调用虚函数是调用子类中的实现。下面对虚函数的实现机理做阐释:
如果一个类中存在虚函数,编译器会为该类创建一个虚函数地址表(vtbl),保存自己类中虚函数的地址。并为改建创建一个指针(vptr),指向这个表。每个类的对象都会有一个vptr,该类的所有对象公用一个vtbl。
当执行上面的pb->print()时,系统会先获取pb的vtbr,得到vtbl后进行分析后得出结果。