任何一个类,如果有虚函数, 这个类的对象比正常的就会大一点.
#include <iostream>
using namespace std;
class A
{
public:
int i;
A():i(10) {}
virtual void f() { cout << "A::f()" << i << endl; }
};
int main()
{
A a;
a.f(); // A::f()10
cout << sizeof(a) << endl; //8,因为有virtual
int *p =(int*)&a;
cout << *p << endl; //835680
return 0;
}
int main()
{
A a;
a.f(); // A::f()10
cout << sizeof(a) << endl; //8,因为有virtual
//原因是里面除了有int i,还有一个vptr
int *p =(int*)&a;
p++;
cout << *p << endl; //10
return 0;
}
//所有有virtual的类的对象里面,头上就会有隐藏的指针vptr,指向一张表叫vtable. vtable里面是所有virtual函数的地址. vtable是类的,不是对象的.
int main()
{
A a,b;
a.f(); // A::f()10
cout << sizeof(a) << endl; //8,因为有virtual
//原因是里面除了有int i,还有一个vptr
int *p =(int*)&a;
int *q =(int*)&b;
int *x = (int*)*p; //vtable里的第一项是什么?
cout << x << endl;//0x2f068
cout << *p << endl << *q << endl; //725088 725088,都指向vptr
return 0;
}
class Shape
{
public:
Shape();
virtual ~Shape();
virtual void render();
void move(const XYPos&);
virtual void resize();
protected:
XYPos center;
};
//任何一个Shape的对象,它里面都有vptr指向vtable和center.
class Ellipse: public Shape
{
public:
Ellipse(float majr,float minr);
virtual void render();
protected:
float major_axis;
float minor_axis;
};
//Ellipse是Shape的子类,它会增加东西. 它也会有vptr,但它会指向自己Ellipse的vtable.
如何发生动态绑定的?
Ellipse对象是可以被当做Shape对象来看待的.
当p所指向render()的时候, 实际上是p所指的对象的第一个地址取出来,从这个地址访问到了vtable, 从这个vtable+2得到render()的地址, 调用那个render()地址函数即可.
Shape vs Ellipse
#include <iostream>
using namespace std;
class A
{
public:
A():i(10) {}
virtual void f() { cout << "A::f()" << i << endl; }
int i;
};
class B:public A
{
public:
B():j(20) {}
virtual void f() { cout << "B::f()" << j << endl; }
};
int main()
{
A a;
B b;
A* p = &b;
p->f(); // B::f() 20
#if 1
a = b;
a.f(); //通过指针动态绑定,现在是静态绑定A::f()
#endif
#if 0
a = b; //b的值给了a,vptr不传递
p = &a;
p->f();//A::f()
#endif
return 0;
}
int main()
{
A a;
B b;
A* p = &a; //p所指的对象是a
int* r = (int*)&a;
int* t = (int*)&b;
*r = *t;
p->f(); //B::f() 32767
return 0;
}