我有几节课,我试图了解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:
  • B::vpointer-在堆栈上
  • A::vpointer-在堆上

  • 它们具有相同的值(value)吗? (包含相同的地址?)
    这里有几个vtable?

    最佳答案

    首先,重要的是要知道C++标准不了解堆栈,堆或vptr。因此,这里所说的一切都取决于实现。

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

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

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

  • 实现相关信息

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

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

    我希望AbstractImage有一个虚拟表(它至少有一个虚拟函数成员),每个实例化的Image<X>都有一个虚拟表(即,一个Image<RGB>和一个Image<short>的虚拟表。ColorImageBWImage只是同义词。仅假设,因为只要遵守标准,编译器就可以不同地实现它。

    附加信息:
  • Storage Layout of Polymorphic Objects:有关单继承情况下vptr和vptr布局的文章
  • Multiple Inheritance Considered Useful:有关在单继承和多继承情况下使用vptr进行内存布局的文章。
  • 10-06 16:02