我有一些课程,我试图了解vptr和vtable在这种情况下是如何工作的。
class RGB {
short value[3];
};
class AbstractImage{
protected:
int n_pixels;
public:
virtual void show() = 0;
virtual AbstractImage* getMe() = 0;
virtual ∼AbstractImage() {};
};
template <typename T> class Image: public AbstractImage {
T* data;
public:
Image<T>(int n) { n_pixles=n; data=new T[n_pixles];}
virtual ∼Image<T>() { delete[] data; }
Image<T>(const Image<T>& rhs) {
n_pixels = rhs.n_pixels;
data = new T[n_pixels];
copyData(rhs);
}
Image<T>& operator=(const Image<T>& rhs) {
n_pixels = rhs.n_pixels;
delete[] data;
data = new T[n_pixels];
copyData(rhs);
return *this;
}
virtual void show() {/*some code*/}
virtual Image<T>* getMe() {return this;}
private:
void copyData(const Image<T>& rhs) {
for(int i=0l i<n_pixels;i++) {
data[i] = rhs.data[i];
}
}
};
typedef class Image<RGB> ColorImage;
typedef class Image<short> BWImage;
我试图弄清楚在运行以下实现后堆栈和堆应该如何:
int main() {
AbstractImage* A = new ColorImage(4);
ColorImage B = colorImage(4);
A->show();
}
从我的理解中创建了2个vptr:
他们有相同的价值吗? (包含相同的地址?) 这里有几个vtable?
答案 0 :(得分:1)
首先,重要的是要知道C ++标准不知道堆栈,堆还是vptr。所以这里可以说的一切都取决于实现。
我们可以从标准中推断出什么?
您的代码会创建2个ColorImage
个对象:
A
实施相关信息
两个对象具有相同的具体类型,即使其中一个是通过指向其基类的指针访问的。
两个对象可能在其内存位置中的某个位置vptr
指向与其具体(实际)类型对应的虚拟表。大多数编译器对每个具体类类型使用一个vptr
。因此vptr
可能都指向同一个虚拟表。
我期望AbstractImage
的虚拟表(它至少有一个虚函数成员),每个实例Image<X>
的虚拟表(即一个用于Image<RGB>
,一个用于Image<short>
ColorImage
。BWImage
和vptr
只是同义词。但正如所说,这只是假设,因为只要符合标准,编译器就可以以不同的方式实现它。
其他信息:
答案 1 :(得分:0)
来自wiki:
通常,编译器为每个类创建一个单独的vtable。创建对象时,会将指向此vtable的指针(称为虚拟表指针,vpointer或VPTR)添加为此对象的隐藏成员。因此,编译器还必须在每个类的构造函数中生成“隐藏”代码,以将新对象的vpointer初始化为其类的vtable的地址。
所以最有可能的vpointers有不同的价值,但我们不能肯定地说。