C++-----虚函数、虚函数指针、虚函数表、通过指针访问类的虚函数成员
1、虚函数继承,派生类赋值给基类
#include<vector>
#include<iostream>
using namespace std;
class Base {
public:
Base() { A(); };
virtual void A() {
cout << "Base::A" << endl;
}
void B() {
cout << "Base::B" << endl;
}
virtual void C() {
cout << "Base::C" << endl;
}
};
class Derive:public Base {
public:
Derive() { A(); };
virtual void A() {
cout << "D::A" << endl;
}
void derive_B() {
cout << "D::B" << endl;
}
virtual void C() {
cout << "D::C" << endl;
}
};
int main() {
Base base_test; //调用基类构造函数 输出Base::A
Derive* derive_ptr;
Derive derive_test; //创建一个派生类会先调用基类构造函数,再调用派生类构造函数 输出
//Base::A,D::A
base_ptr = &derive_test;//将派生类对象赋值给基类,会对派生类作出裁剪。也就是会去掉derive_B
base_ptr->A(); //调用的是派生类的A(); 输出D::A
return 0;
}
2、分析
首先,创建一个对象则会调用构造函数,创建一个派生类对象时,会先调用基类的构造函数,然后调用派生类自己的构造函数,析构的时候顺序相反。可以将一个派生类对象赋值给基类指针,但是这样会对派生类作出裁剪。也就是上面的base_ptr指向的对象里面没有派生类里独有的成员函数,并且调用虚函数的话调用的会是派生类的虚函数。这样可以得到其结果:

3、虚函数表、虚函数指针、通过指针访问类的虚函数成员
#include<vector>
#include<iostream>
using namespace std;
class Base {
public:
Base() { A();
};
void test(){
cout << "test" << endl;
}
virtual void A() {
cout << "Base::A" << endl;
}
void B() {
cout << "Base::B" << endl;
}
virtual void C() {
cout << "Base::C" << endl;
}
virtual void D() {
cout << "Base::D" << endl;
}
public:
int a;
int b;
};
class Derive:public Base {
public:
Derive() { A(); };
virtual void A() {
cout << "Der::A" << endl;
}
void derive_B() {
cout << "Der::B" << endl;
}
virtual void C() {
cout << "Der::C" << endl;
}
virtual void D() {
cout << "Der::D" << endl;
}
};
typedef void(*Pfun)();
int main() {
Base base_test; //创建对象会输出Base::A
Base* base_ptr;
//虚函数指针一般存放在一个类对象的最开始的地方
long *address =(long*)(&base_test);
cout << "基类虚函数表地址" << (long*)&base_test<<endl;
cout << "基类虚函数表地址" << address << endl;
//首先取到虚函数表的地址,这个地址里存放的是虚函数也就是第一个虚函数的地址,取出这个地址。
cout << "基类虚函数表第一个函数的地址" << (long*)*(long*)&base_test<<endl;
cout << "基类虚函数表第一个函数的地址" << (long*)(*address)<< endl;
//在long*的基础上加1则指向第二个虚函数的地址
cout << "基类虚函数表第二个函数的地址" << (((long*)(*address))+1) << endl;
cout << "基类虚函数表第三个函数的地址" << ((long*)(*(address)) + 2) << endl;
//上面得到虚函数的地址,取出这个地址的值然后再用函数指针指向它。
Pfun p1 = (Pfun)*((long*)(*address)); //函数指针
Pfun p2 = (Pfun)*(((long*)(*address)) + 1);
Pfun p3 = (Pfun)*(((long*)(*(address)) + 2));
p1(); //基类第一个虚函数
p2(); //基类第二个虚函数
p3(); //基类第三个虚函数
Derive derive_test;
long * address2 = (long*)(&derive_test);
cout << "派生类虚函数表地址" << (long*)&derive_test << endl;
cout << "派生类虚函数表第一个函数的地址" << (long*)*(long*)&derive_test << endl;
cout << "派生类虚函数表第二个函数的地址" << ((long*)(*address2)+1) << endl;
cout << "派生类虚函数表第二个函数的地址" << ((long*)(*address2) + 2) << endl;
Pfun p4 = (Pfun)*((long*)(*address2));
Pfun p5 = (Pfun)*(((long*)(*address2)) + 1);
Pfun p6 = (Pfun)*(((long*)(*(address2)) + 2));
p4();
p5();
p6();
return 0;
}
4、分析
首先记住函数指针的声明,typedef的用法和define的用法的差别。其余看代码注释。输出结果如下:


浙公网安备 33010602011771号