2

我有几节课,我试图了解 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 - 在堆上

它们是否具有相同的价值?(包含相同的地址?)这里有多少个 vtable?

4

2 回答 2

1

首先,重要的是要知道 C++ 标准不知道堆栈、堆和 vptr。所以这里所说的一切都是依赖于实现的。

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

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

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

实施相关信息

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

两个对象可能在它们的内存位置的某个地方都有一个vptr指向对应于它们的具体(真实)类型的虚拟表。大多数编译器对vptr每个具体的类类型使用一个。因此,两者vptr可能都指向同一个虚拟表。

我希望有一个虚拟表AbstractImage(它至少有一个虚拟函数成员),每个实例化一个虚拟表Image<X>(即一个 forImage<RGB>和一个 for Image<short>. ColorImage并且BWImage只是同义词。但正如所说,这只是假设,因为编译器是只要遵守标准,就允许以不同的方式实施它。

附加信息:

于 2018-03-11T11:11:46.567 回答
0

来自维基:

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

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

于 2018-03-11T10:58:01.320 回答