2

I have a few classes and I'm trying to understand how the vptr and vtable work in this situation.

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;

I am trying to figure out how the stack and heap should be after running the following implementation:

int main() {
    AbstractImage* A = new ColorImage(4);
    ColorImage B = colorImage(4);
    A->show();
}

from my understanding there are 2 vptr created:

  1. B::vpointer - On the stack
  2. A::vpointer - On the heap

Do they have the same value? (contain the same address?) How many vtables are there here?

Christophe
  • 68,716
  • 7
  • 72
  • 138
Adam Morad
  • 167
  • 1
  • 7
  • 2
    That's an implementation detail of the particular C++ implementation you are using. You never told us, which compiler you are using, so there will be no answer readily available. – IInspectable Mar 11 '18 at 10:59
  • You need to consult the documentation of your C++ implementation, and you should definitely use your debugger to find out more about its internal workings. Nothing of this is standardised. – Christian Hackl Mar 11 '18 at 11:20
  • When I drive a car I do not much care about how the manufactures arranged stuff under the bonnet (hood for the Yanks). Why does it matter how it is implemented for you? I you are going to try to fiddle with the mechanism the code is a) not potable b) Can break at the later version of the compiler c) Code is not maintainable. – Ed Heal Mar 11 '18 at 11:35
  • The thing is, it was part of an exam where they asked if the vptr definitely contain the same address, if there is a possibility that they don't - I could appeal on the grade. – Adam Morad Mar 11 '18 at 11:41
  • @AdamMorad - If it was in an exam - it is an unfair question. It is up to the manufactures of the compiler. As long as it adheres to the standard. – Ed Heal Mar 11 '18 at 11:45

2 Answers2

1

First, it's important to know that the C++ standard doesn't know about stack, heap nor vptr. So everything that can be said here is implementation dependent.

What can we deduce from the standard?

Your code creates 2 ColorImage objects:

  • an object in the free store, of dynamic storage duration (aka "heap" in your terminology), and which pointer is stored in A
  • a local object of automatic duration (aka "stack" in your terminology)
  • it's two different objects

Implementation dependent info

Both objects have the same concrete type, even if one of the two is access via a pointer to its base class.

Both objects may have somewhere in their memory location a vptr pointing to the virtual table corresponding to their concrete (real) type. Most compilers use one vptr per concrete class type. Hence both vptr would probably point to the same virtual table.

I'd expect a virtual table for AbstractImage (it has at least one virtual function member), a virtual table for each instantiated Image<X> (i.e. one for Image<RGB> and one for Image<short>. ColorImage and BWImage are only synonyms. But as said, this are only hypotheses, as compilers are allowed to implement it differently as long as the standard is respected.

Additional information:

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • So it is compiler-dependent? Is there a compiler that would cause the virtual pointer to point to different address? – Adam Morad Mar 11 '18 at 11:31
  • 1
    @AdamMorad not as far as I know, because very often the vptr is also used to store a pointer to the type info (e.g.: http://refspecs.linuxbase.org/cxxabi-1.83.html#vtable). But you should avoid relying on any assumption on vptr in your code. – Christophe Mar 11 '18 at 11:35
  • @AdamMorad - It might not be a pointer in the conventional sense - Could be an index to an vtable array. Who knows? As long as the compiler adheres to the standard they can implement in a multitude of possibilities. – Ed Heal Mar 11 '18 at 11:39
  • The thing is, it was part of an exam where they asked if the vptr definitely contain the same address, if there is a possibility that they don't - I could appeal on the grade. – Adam Morad Mar 11 '18 at 11:41
0

From wiki:

Typically, the compiler creates a separate vtable for each class. When an object is created, a pointer to this vtable, called the virtual table pointer, vpointer or VPTR, is added as a hidden member of this object. As such, the compiler must also generate "hidden" code in the constructors of each class to initialize a new object's vpointer to the address of its class's vtable.

So most likely vpointers have different value, but we can't say it for sure.

Yola
  • 18,496
  • 11
  • 65
  • 106