таблица виртуальных методов для множественного наследования

Я читаю эту статью " Таблица виртуальных методов "

Пример в приведенной выше статье:

class B1 {
public:
  void f0() {}
  virtual void f1() {}
  int int_in_b1;
};

class B2 {
public:
  virtual void f2() {}
  int int_in_b2;
};

class D : public B1, public B2 {
public:
  void d() {}
  void f2() {}  // override B2::f2()
  int int_in_d;
};

B2 *b2 = new B2();
D  *d  = new D();

В статье автор вводит представление о том, что структура памяти объекта d выглядит следующим образом:

          d:
D* d-->      +0: pointer to virtual method table of D (for B1)
             +4: value of int_in_b1
B2* b2-->    +8: pointer to virtual method table of D (for B2)
             +12: value of int_in_b2
             +16: value of int_in_d

Total size: 20 Bytes.

virtual method table of D (for B1):
  +0: B1::f1()  // B1::f1() is not overridden

virtual method table of D (for B2):
  +0: D::f2()   // B2::f2() is overridden by D::f2()

Вопрос касается d->f2(). Вызов d->f2() передает указатель B2 как указатель this, поэтому мы должны сделать что-то вроде:

(*(*(d[+8]/*pointer to virtual method table of D (for B2)*/)[0]))(d+8) /* Call d->f2() */

Почему мы должны передавать указатель B2 как this указатель не является исходным указателем D ??? На самом деле мы вызываем D :: f2 (). Исходя из моего понимания, мы должны передать указатель D в виде this в функцию D :: f2 ().

___ обновление ____

Если передать указатель B2 в виде this to D :: f2 (), Что если мы хотим получить доступ к членам класса B1 в D :: f2 ()? ? Я считаю, что указатель B2 (это) отображается следующим образом:

          d:
D* d-->      +0: pointer to virtual method table of D (for B1)
             +4: value of int_in_b1
B2* b2-->    +8: pointer to virtual method table of D (for B2)
             +12: value of int_in_b2
             +16: value of int_in_d

У него уже есть определенное смещение начального адреса этой непрерывной структуры памяти. Например, мы хотим получить доступ к b1 внутри D :: f2 (), я думаю, во время выполнения это будет выглядеть примерно так: *(this+4) (this указывает на тот же адрес, что и b2 ) что будет указывать b2 в B? ???

7 голосов | спросил Fihop 10 J0000006Europe/Moscow 2015, 23:45:09

1 ответ


0

Мы не можем передать указатель D на виртуальную функцию, переопределяющую B2::f2(), потому что все переопределения одной и той же виртуальной функции должны принимать одинаковое расположение памяти.

Поскольку функция B2::f2() ожидает B2 Макет памяти объекта, передаваемого ему как указатель this, т.е.

b2:
  +0: pointer to virtual method table of B2
  +4: value of int_in_b2

переопределяющая функция D::f2() также должна ожидать такой же компоновки. В противном случае функции больше не будут взаимозаменяемыми.

Чтобы понять, почему взаимозаменяемость имеет значение, рассмотрите следующий сценарий:

class B2 {
public:
  void test() { f2(); }
  virtual void f2() {}
  int int_in_b2;
};
...
B2 b2;
b2.test(); // Scenario 1
D d;
d.test(); // Scenario 2

B2::test() необходимо вызвать f2() в обоих сценариях. У него нет дополнительной информации, чтобы сказать, как указатель this должен быть настроен при выполнении этих вызовов * . Вот почему компилятор передает фиксированный указатель, поэтому test() вызывает f2 будет работать как с D::f2(), так и с B2::f2()

* Другие реализации могут очень хорошо передать эту информацию; однако реализация множественного наследования, описанная в статье, этого не делает.

ответил dasblinkenlight 10 J0000006Europe/Moscow 2015, 23:59:41

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132