У меня есть несколько классов, и я пытаюсь понять, как 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:
Они имеют одинаковую ценность? (содержать тот же адрес?)
Сколько здесь vtables?
Во-первых, важно знать, что стандарт C ++ не знает ни о стеке, ни о куче, ни о vptr. Так что все, что можно здесь сказать, зависит от реализации.
Что мы можем вывести из стандарта?
Ваш код создает 2 ColorImage
объекты:
A
Информация, зависящая от реализации
Оба объекта имеют один и тот же конкретный тип, даже если один из них является доступом через указатель на его базовый класс.
Оба объекта могут иметь где-то в своей памяти vptr
указывая на виртуальную таблицу, соответствующую их конкретному (реальному) типу. Большинство компиляторов используют один vptr
по конкретному типу класса. Отсюда оба vptr
вероятно, будет указывать на ту же виртуальную таблицу.
Я ожидаю виртуальный стол для AbstractImage
(имеет по крайней мере один виртуальный член функции), виртуальную таблицу для каждого экземпляра Image<X>
(то есть один для Image<RGB>
и один для Image<short>
, ColorImage
а также BWImage
только синонимы. Но, как уже говорилось, это всего лишь гипотезы, поскольку компиляторы могут реализовывать его по-разному, при условии соблюдения стандарта.
Дополнительная информация:
vptr
в случае единичного и множественного наследования. Из вики:
Как правило, компилятор создает отдельную таблицу для каждого класса. Когда объект создается, указатель на эту виртуальную таблицу, называемый указателем виртуальной таблицы, vpointer или VPTR, добавляется в качестве скрытого члена этого объекта. Таким образом, компилятор также должен генерировать «скрытый» код в конструкторах каждого класса, чтобы инициализировать vpointer нового объекта по адресу vtable его класса.
Так что, скорее всего, vpointers имеют разную ценность, но мы не можем сказать это наверняка.