Указатели и нарезка объектов

Я изучаю сложный способ нарезки объектов, и мне интересно, возможно ли когда-либо указатель быть нарезанным на объекте. Другими словами:

  • Могут ли указатели быть жертвами нарезки объектов или вы всегда защищены от нарезки объектов, если используете указатель?

2

Решение

Да — указатель на base требуется, чтобы иметь возможность ссылаться на объект любого типа, полученный из base и по-прежнему сохраняют правильный тип для производного объекта (и для чего бы это ни стоило, то же самое верно и для ссылок).

3

Другие решения

Это зависит от того, насколько свободно вы хотите определить «нарезку». В некотором смысле, когда вы указываете на производный объект с базовым указателем (или ссылкой), любые не виртуальные функции будут разделены. Например:

class A {
void Print() { cout << "Class A\n"; }
};

class B : public A {
void DoB() {}
void Print() { cout << "Class B\n"; }
};

B b;
A* a = &b;
a->DoB(); // Won't compile!
a->Print(); // Prints "Class A", not "Class B"

Призыв к DoB не работает, потому что мы используем указатель на Aтак что компилятор не знает, что он может вызвать DoB на этот указатель. Таким образом, вы теряете часть B, так что вы можете думать об этом как о форме нарезки.

В частности, последняя строка является примером явления, называемого «сокрытие имени». Так как Print не был объявлен virtual в базовом классе, и наш указатель имеет тип A, компилятор не знает, что он должен вызывать B::Print вместо A::Print,

Важный пример этой проблемы вступает в игру с вашим деструктором:

class A {
~A() {}
};

class B : public A {
std::vector<int> v;
};

A* a = new B;
delete a; // What happens to B::v? Undefined behaviour!

Здесь, потому что деструктор не был отмечен как virtualназывается деструктором базового класса в не виртуальном контексте, что означает BДеструктор не будет вызван.

10

По вопросам рекламы [email protected]