VPTR的初始化之二???

时间:2022-05-03 19:47:13
VPTR在构造函数中的初始化操作时机应该是“调用base class constructor以后,而在程序员提供的码或是在member initialization list的操作之前”。大家来探讨一下这个话题,下面是本人的一点见解:对虚拟函数的调用最终是通过一个构造完毕的对象(不管是通过它的指针还是引用)来调用,那么把当一个对象构造完毕以后,其VPTR肯定已经指向正确的VTBL,那么在一个继承体系中,各个层次的对象中的VPTR均已指向各自的VTBL,所以当利用不同的对象(当然这些对象位于一个继承体系中)来调用虚拟函数时,就可以调用到各自的函数版本!!!


欢迎大家来信探讨:chouzhezhe@163.com

10 个解决方案

#1


jinfeng_Wang(多看一页书,少问一个问题!) :
VPTR不在VTBL中,VPTR是包含在每一个对象中,而一个类才有唯一的一个VTBL!!!

#2


我是这样想的:

class base
{
...
virtual void print(){cout << "base";};
}

class derived : public base
{
...
virtual void print() { cout <<"derived";}
}

base *basePtr;
derived a;
basePtr = &a;
basePtr -> print();

过程是这样的: 

basePtr = &a;//先指向a,然后复引用指针,指向derived vtable的指针开始。

basePtr->print();

// 复引用a的vtable指针,取得derived vtable
// 跳过n个字节(视成员函数个数而定),选择print()函数指针
// 复引用该函数指针,构成要执行的实际函数名,并用函数调用运算符()执行
   响应的print()函数。


以上是我的理解,请指教。

#3


我?

请大侠明示,谢谢

#4


以下列代码测试(Release故意放构造函数里的)
class A
{
public:
int i;
A(int n)
:i(n)
{
Release();
}
virtual ~A()
{
}
virtual void Release()
{
}
};
class B : public A
{
public:
int j;
B(int n)
:A(n),j(n)
{
Release();
}
virtual ~B()
{
}
virtual void Release()
{
}
};

B b(3);
结果:>
B::B(3)
A::A(3)
A::i(3)
A::__vfptr
B::j(3)
B::__vfptr
完成构造.

#5


faint! such a basic thing.
each object(with virtual function) has at least one pointer which points to the vtable. 
the vtable contains function pointers of each virtual function.

got it?

why an object need a pointer to vtable?

give you a pointer to an object, tell you the interface type, do you know where is the vtable? If you know it at compile time, then it's not late binding, not virtual function at all.

"每个对象都知道它的数据类型是什么"
this is simply wrong! without a pointer to the vtable, how can it know? 

class B:public A{.....};
class C:public A{.....};
void f(A* pa){}
how do you know the pa is of type A or B or C at compile time?

#6


jinfeng_Wang(多看一页书,少问一个问题!) 
一个类包含一个VTable,VPTR是什么概念呢?
是指向虚拟函数的指针,got it?

既然是指针,那么它放在哪儿呢?VTable中!
当我们需要调用虚拟函数的时候
class *a =new A;
a->virtualfunction();

相当于对于*(VTable+i) 取得VPTR   //设VTable为某个地址 ,i是该VPTR对于首地址的偏移量
然后(*VPTR)() 调用该虚拟函数
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

VTPR怎么可能会放在VTable中呢。如果一个类有虚函数,那么它明显是比没有虚函数的类多处4个字节。这4个字节给是存放VPTR。看看这个程序#include <iostream>
using namespace std;

class BaseA
{
int i;
};

class BaseB
{
public:
virtual Test();
int i;
};

class Derived: BaseB
{
int i;
};

int main()
{
cout << sizeof (BaseA) << endl;
cout << sizeof (BaseB) << endl;
cout << sizeof (Derived) << endl;
return 0;
}

#7


vptr是包含在类对象里的,它指向vtable.
jinfeng_Wang(多看一页书,少问一个问题!) 的观点从根本上来讲是错的。
每个virtual function 的位置在编译时就已经确定下来,即在vtable的那一个solt中是已知的,函数的调用被转化为(*vptr[i])(this);i为已知的虚函数索引。

#8


楼主很对。

#9


我已经彻底弄明白了虚拟函数的机制了,谢谢大家的支持,可以参考《Tinking in C++》的有关章节,但是尧死亡很多的脑细胞!!!

#10


to jinfeng_Wang(多看一页书,少问一个问题!) 

你的观点我有点异议,vptr是指向vtable的指针,每个对象都有一个vptr,一般是存放在对象的前几个字节中(一般是四个字节),但是每个类只有一个vtable.这一点《Inside the c++ object model》讲得很清楚。

#1


jinfeng_Wang(多看一页书,少问一个问题!) :
VPTR不在VTBL中,VPTR是包含在每一个对象中,而一个类才有唯一的一个VTBL!!!

#2


我是这样想的:

class base
{
...
virtual void print(){cout << "base";};
}

class derived : public base
{
...
virtual void print() { cout <<"derived";}
}

base *basePtr;
derived a;
basePtr = &a;
basePtr -> print();

过程是这样的: 

basePtr = &a;//先指向a,然后复引用指针,指向derived vtable的指针开始。

basePtr->print();

// 复引用a的vtable指针,取得derived vtable
// 跳过n个字节(视成员函数个数而定),选择print()函数指针
// 复引用该函数指针,构成要执行的实际函数名,并用函数调用运算符()执行
   响应的print()函数。


以上是我的理解,请指教。

#3


我?

请大侠明示,谢谢

#4


以下列代码测试(Release故意放构造函数里的)
class A
{
public:
int i;
A(int n)
:i(n)
{
Release();
}
virtual ~A()
{
}
virtual void Release()
{
}
};
class B : public A
{
public:
int j;
B(int n)
:A(n),j(n)
{
Release();
}
virtual ~B()
{
}
virtual void Release()
{
}
};

B b(3);
结果:>
B::B(3)
A::A(3)
A::i(3)
A::__vfptr
B::j(3)
B::__vfptr
完成构造.

#5


faint! such a basic thing.
each object(with virtual function) has at least one pointer which points to the vtable. 
the vtable contains function pointers of each virtual function.

got it?

why an object need a pointer to vtable?

give you a pointer to an object, tell you the interface type, do you know where is the vtable? If you know it at compile time, then it's not late binding, not virtual function at all.

"每个对象都知道它的数据类型是什么"
this is simply wrong! without a pointer to the vtable, how can it know? 

class B:public A{.....};
class C:public A{.....};
void f(A* pa){}
how do you know the pa is of type A or B or C at compile time?

#6


jinfeng_Wang(多看一页书,少问一个问题!) 
一个类包含一个VTable,VPTR是什么概念呢?
是指向虚拟函数的指针,got it?

既然是指针,那么它放在哪儿呢?VTable中!
当我们需要调用虚拟函数的时候
class *a =new A;
a->virtualfunction();

相当于对于*(VTable+i) 取得VPTR   //设VTable为某个地址 ,i是该VPTR对于首地址的偏移量
然后(*VPTR)() 调用该虚拟函数
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

VTPR怎么可能会放在VTable中呢。如果一个类有虚函数,那么它明显是比没有虚函数的类多处4个字节。这4个字节给是存放VPTR。看看这个程序#include <iostream>
using namespace std;

class BaseA
{
int i;
};

class BaseB
{
public:
virtual Test();
int i;
};

class Derived: BaseB
{
int i;
};

int main()
{
cout << sizeof (BaseA) << endl;
cout << sizeof (BaseB) << endl;
cout << sizeof (Derived) << endl;
return 0;
}

#7


vptr是包含在类对象里的,它指向vtable.
jinfeng_Wang(多看一页书,少问一个问题!) 的观点从根本上来讲是错的。
每个virtual function 的位置在编译时就已经确定下来,即在vtable的那一个solt中是已知的,函数的调用被转化为(*vptr[i])(this);i为已知的虚函数索引。

#8


楼主很对。

#9


我已经彻底弄明白了虚拟函数的机制了,谢谢大家的支持,可以参考《Tinking in C++》的有关章节,但是尧死亡很多的脑细胞!!!

#10


to jinfeng_Wang(多看一页书,少问一个问题!) 

你的观点我有点异议,vptr是指向vtable的指针,每个对象都有一个vptr,一般是存放在对象的前几个字节中(一般是四个字节),但是每个类只有一个vtable.这一点《Inside the c++ object model》讲得很清楚。