搞清楚vptr字段

时间:2018-03-11 10:42:13

标签: c++ inheritance polymorphism vptr virtual-table

我有一些课程,我试图了解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:

  1. B :: vpointer - 在堆栈上
  2. A :: vpointer - 在堆上
  3. 他们有相同的价值吗? (包含相同的地址?) 这里有几个vtable?

2 个答案:

答案 0 :(得分:1)

首先,重要的是要知道C ++标准不知道堆栈,堆还是vptr。所以这里可以说的一切都取决于实现。

我们可以从标准中推断出什么?

您的代码会创建2个ColorImage个对象:

  • 免费商店中的一个对象,具有动态存储持续时间(在术语中称为“堆”),以及哪个指针存储在A
  • 自动持续时间的本地对象(在术语中称为“堆栈”)
  • 这是两个不同的对象

实施相关信息

两个对象具有相同的具体类型,即使其中一个是通过指向其基类的指针访问的。

两个对象可能在其内存位置中的某个位置vptr指向与其具体(实际)类型对应的虚拟表。大多数编译器对每个具体类类型使用一个vptr。因此vptr可能都指向同一个虚拟表。

我期望AbstractImage的虚拟表(它至少有一个虚函数成员),每个实例Image<X>的虚拟表(即一个用于Image<RGB>,一个用于Image<short> ColorImageBWImagevptr只是同义词。但正如所说,这只是假设,因为只要符合标准,编译器就可以以不同的方式实现它。

其他信息:

答案 1 :(得分:0)

来自wiki:

  

通常,编译器为每个类创建一个单独的vtable。创建对象时,会将指向此vtable的指针(称为虚拟表指针,vpointer或VPTR)添加为此对象的隐藏成员。因此,编译器还必须在每个类的构造函数中生成“隐藏”代码,以将新对象的vpointer初始化为其类的vtable的地址。

所以最有可能的vpointers有不同的价值,但我们不能肯定地说。