有关知识复习
1:动态多态
动态绑定:在程序执行期间(非编译期间)判断所引用对象的实际类型,根据其实际类型调用相应的方法。
2:动态多态具体实现、
class A
{
public:
virtual void funtest1()
{
cout << "A.funtest1" << endl;
}
virtual void funtest2()
{
cout << "A.funtest2 " << endl;
}
int _a;
};
class B1 : public A
{
public:
virtual void funtest1()
{
cout << "B1.funtest1" << endl;
}
virtual void funtest3()
{
cout << "B1.funtest3" << endl;
}
int _b1;
};
void funtest(A &s)
{
s.funtest1();
s.funtest2();
}
int main()
{
B1 b1;
funtest(b1);
system("pause");
return 0;
}
在funtest函数里面用基类的引用作为参数,真正传过去的是派生类的对象,而且在派生类里面是对funtest1函数进行了重写的,所以在执行期间会根据所引用的具体类型调用相应的函数。
3:虚表的简单查看
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
using namespace std;
class A
{
public:
virtual void funtest1()
{
cout << "A.funtest1" << endl;
}
virtual void funtest2()
{
cout << "A.funtest2 " << endl;
}
int _a;
};
class B1 : public A
{
public:
virtual void funtest1()
{
cout << "B1.funtest1" << endl;
}
virtual void funtest3()
{
cout << "B1.funtest3" << endl;
}
int _b1;
};
typedef void(*pvf)();
void Print()
{
B1 b1;
b1._a = 1;
b1._b1 = 2;
pvf *fun = (pvf *)*(int*)&b1;
while (*fun)
{
(*fun)();
fun++;
}
}
void FunTest()
{
cout << sizeof(B1) << endl;
}
int main()
{
Print();
FunTest();
system("pause");
return 0;
}
通过求取B1类的大小可以在内存中查看b1的存储方式,图上所表示的是虚表指针指向的虚表和打印出来的虚表的实际对应.通过对b1对象内存的分析可以知道除了b1所含的两个整型意外,最上面的四个字节就是虚表指针,指向的虚表通过打印的方式显示出来如图中所示,由于B1对A类是公有继承而且在B1类中对基类的funtest1函数进行了重写,所以派生类B1的虚表就应该是图中所显示的内容。
菱形虚拟继承中派生类的虚表指针以及偏移量指针
class A
{
public:
virtual void funtest1()
{
cout << "A.funtest1" << endl;
}
virtual void funtest2()
{
cout << "A.funtest2 " << endl;
}
int _a;
};
class B1 :virtual public A
{
public:
virtual void funtest1()
{
cout << "B1.funtest1" << endl;
}
virtual void funtest3()
{
cout << "B1.funtest3" << endl;
}
int _b1;
};
class B2 :virtual public A
{
public:
virtual void funtest2()
{
cout << "B2.funtest2" << endl;
}
virtual void funtest4()
{
cout << "B2.funtest4" << endl;
}
int _b2;
};
class C :public B1, public B2
{
public:
virtual void funtest3()
{
cout << "C.funtest3" << endl;
}
virtual void funtest4()
{
cout << "C.funtest4" << endl;
}
virtual void funtest5()
{
cout << "C.funtest5" << endl;
}
int _c;
};
typedef void(*pvf)();
void Print()
{
A a;
/*c._a = 1;
c._b1 = 2;
c._b2 = 3;
c._c = 4;*/
pvf *fun = (pvf *)*(int*)&a;
while (*fun)
{
(*fun)();
fun++;
}
}
void FunTest()
{
cout << sizeof(C) << endl;
}
int main()
{
Print();
FunTest();
system("pause");
return 0;
}
如图所示,就是C类对象在内存空间的具体存储,红色线所指函数或者数字即为C类对象中的指针所指内容,要么是偏移量大小,要么是虚表指针,特别之处在于两个 ‘-4’,表示的是从该位置向上偏移四个字节才是C通过这个继承体系继承的B1,B2 类在C中存储的起始位置。12和24就是偏移量大小,若C B1 B2需要访问基类成员所需要偏移的字节数。