#include<iostream>
using namespace std;
class X
{
int a;
int b;
public:
void f(int a)
{
cout<<"\nInside X";
}
virtual void abc ()
{
cout<<"\nHello X";
}
};
class Y : public X
{
int a;
public:
void f(int a, int b)
{
cout<<"\nInside Y";
}
void abc()
{
cout<<"\nHello Y";
}
};
int main()
{
X a;
cout<<sizeof(X);
Y b;
cout<<sizeof(Y);
X *h = new Y;
h->abc();
}
Run Code Online (Sandbox Code Playgroud)
我理解类X的大小是12个字节的原因是因为它包含一个到虚拟表的vptr(虚拟指针).无论如何我可以读取这个虚拟表,如果没有,至少可以访问虚拟指针.我尝试过使用工会,但它给了我一些错误.
另外,当我调用h-> abc()时,它如何知道类的对象,h指向?我认为大部分都是在编译时完成的.但是当你有一个指向派生类的基类指针时,它如何知道要执行哪个类函数.考虑这两种情况
X *h = new X;
h->abc();/* This would call the abc function in X */
Run Code Online (Sandbox Code Playgroud)
和
X *h = new Y;
h->abc();/* This would call the abc function in Y*/
Run Code Online (Sandbox Code Playgroud)
我读过,h指针会转到它指向的对象的vtable,因此会调用该函数吗?但是如何在运行时实现?
好的,第一个问题:我举一个可能更好理解的例子!

#include<iostream>
using namespace std;
class Base1 {
public:
int ibase1;
Base1():ibase1(10) {}
virtual void f() { cout << "Base1::f()" << endl; }
virtual void g() { cout << "Base1::g()" << endl; }
virtual void h() { cout << "Base1::h()" << endl; }
};
class Base2 {
public:
int ibase2;
Base2():ibase2(20) {}
virtual void f() { cout << "Base2::f()" << endl; }
virtual void g() { cout << "Base2::g()" << endl; }
virtual void h() { cout << "Base2::h()" << endl; }
};
class Base3 {
public:
int ibase3;
Base3():ibase3(30) {}
virtual void f() { cout << "Base3::f()" << endl; }
virtual void g() { cout << "Base3::g()" << endl; }
virtual void h() { cout << "Base3::h()" << endl; }
};
class Derive : public Base1, public Base2, public Base3 {
public:
int iderive;
Derive():iderive(100) {}
virtual void f() { cout << "Derive::f()" << endl; }
virtual void g1() { cout << "Derive::g1()" << endl; }
};
Run Code Online (Sandbox Code Playgroud)
这是一个派生类的内存等级,它实现了三个基类base1,base2,base3,你在其中:
Base1 *p1 = new Derive();
Base2 *p2 = new Derive();
Base3 *p3 = new Derive();
Run Code Online (Sandbox Code Playgroud)
p1将指向vtale1,p2将指向vtable2,p3将指向vtable3,如果调用某个虚函数,它将找到非常虚拟的表并获取地址!
在你的代码中:
X *h = new Y;
Run Code Online (Sandbox Code Playgroud)
h将指向Y的内存的开始位置,这是X的虚拟表,他将找到abc()在Y中实现的地址!
你的第二个问题:
编译器会将成员函数视为普通函数,因此它将成员函数的地址放入其中code section,因此它不会占用内存!
如果你想阅读虚拟表,你可以尝试这样:我在gcc4.7的例子中尝试过
typedef void(*Func)(void);
Derive d;
int **pd = (int **)(&d);
int i = 0;
while(i < 4)
{
Func f = (Func)pd[0][i];
f();
i++;
}
int s = (int)(pd[1]);
cout << s << endl;
i = 0;
cout << "===============================================" << endl;
while(i < 3)
{
Func f = (Func)pd[2][i];
f();
i++;
}
s = (int)(pd[3]);
cout << s << endl;
cout << "===============================================" << endl;
i = 0;
while(i < 3)
{
Func f = (Func)pd[4][i];
f();
i++;
}
s = (int)(pd[5]);
cout << s << endl;
s = (int)(pd[6]);
cout << s << endl;
Run Code Online (Sandbox Code Playgroud)
你会得到如下结果:
Derive::f()
Base1::g()
Base1::h()
Derive::g1()
10
===============================================
Derive::f()
Base2::g()
Base2::h()
20
===============================================
Derive::f()
Base3::g()
Base3::h()
30
100
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
268 次 |
| 最近记录: |