Что касается виртуальных функций, что происходит при доступе к определенным методам, когда они объявлены виртуальными, а когда нет - PullRequest
0 голосов
/ 28 октября 2011

Для виртуальных функций: что происходит при доступе к определенным методам, когда они объявлены виртуальными, а когда нет.

моя идея:

если он виртуальный, вызывающий экземпляр будет искать функцию в своей таблице виртуальных функций; если это указатель базового экземпляра, указывающий на производный экземпляр, будет вызвана реализация виртуальной функции производного экземпляра. Если это не виртуальная функция, вызывается вызов функции вызывающего экземпляра.

Верно?

Ответы [ 2 ]

1 голос
/ 28 октября 2011

С точки зрения стандартного языка, сказать больше нечего, чем то, что вы, вероятно, уже знаете: если функция виртуальная, то ее вызов по любой ссылке или указателю базового класса вызовет самую производную фактическую функцию.

Вот и все.Все, что имеет значение, это поведение.

То, что вам действительно нужно, это то, как компиляторы реализуют это.Действительно, vtable является наиболее популярным способом реализации виртуальной диспетчеризации.По сути, это список указателей функций, который поддерживается для каждого класса, имеющего виртуальные функции.(Помните, что наследование от класса с виртуальными функциями автоматически делает эти функции виртуальными снова в производном классе.)

Однако способ, которым компилятор на самом деле вызывает функцию, меняется.

  • Если функция не виртуальная, она известна во время компиляции и отправляется статически в функцию-член типа статического класса, для которого она была вызвана.

  • Если функция виртуальная, но компилятор может доказать динамический тип базовой ссылки / указателя во время компиляции, он может выбрать непосредственный вызов функции соответствующего производного класса.

  • Если динамический тип не может быть выведен компилятором, диспетчеризация функции происходит во время выполнения путем поиска указателя функции фактической (наиболее производной) функции в виртуальной таблице.

Пример:

struct A {
  void foo();
  virtual void bar();
};
struct B : A {
  void foo(); // hides A::foo() -- very bad style
  void bar(); // automatically virtual!!
};

int main() {
  B x;
  A * a1 = &x;  // pointer-to-base;
  A * a2 = get_pointer();

  a1->foo(); // static dispatch to A::foo() (non-virtual function)
  a1->bar(); // dispatch to B::foo(), possibly resolved statically
  a2->bar(); // dynamically dispatched to whatever the most derived class is
}
0 голосов
/ 28 октября 2011

правый. Если вы вызываете функцию virtual через указатель базового класса, вызывается переопределение. С другой стороны, если вы вызываете не virtual функцию через указатель базового класса, будет вызвана функция базового класса.

То же самое верно при вызове через ссылки вместо указателей.

При работе с указателями базового класса следует помнить следующее: Slicing . Если вы сделаете это:

Base* pb = new Der;
Base other = *pb;

other разрезал объект, и все Der -нессы исчезли.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...