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的用法的差别。其余看代码注释。输出结果如下:

posted @ 2019-05-22 18:45  吾之求索  阅读(316)  评论(0)    收藏  举报