singalen: (2002)
[personal profile] singalen
Продолжаем набивать журнал контентом.
Что будет, если указателю на функцию-член присвоить указатель на виртуальный метод предка, а потом вызвать её на экземпляре потомка?
А для невиртуальной функции?
#include <iostream>

class A
{
public:
  virtual void f() { std::cout << "A::f()\n"; };
  void g() { std::cout << "A::g()\n"; };
};

class B : public A
{
public:
  virtual void f() { std::cout << "B::f()\n"; };
  void g() { std::cout << "B::g()\n"; };
};

typedef void (A::*VirtualFunctionPointer) ();

int main()
{
  A a;
  B b;
  B* pb = &b;

  VirtualFunctionPointer p = &A::f;

  (pb->*p) ();

  p = &A::g;
  (pb->*p) ();

  return 0;
}

И на gcc, и на MSVC выдаёт одно и то же:
B::f()
A::g()

Вывод интересен: указатель на функцию-член хранит И индекс в VMT, И указатель на функцию. Ну и флаг, указывающий, что именно хранится.

fun

1/2/06 06:37 (UTC)
Posted by (Anonymous)
Интерестный пример. Но на мой взгляд польза примера в том, что после операции p=&A::f; С++ не хранит адрес этих функций, а точнее стандартом не прописаны значения указателя на функцию. Поэтому то, что хранится в p, после каждого присваивания не известно(например, это индекс в виртуальной таблице).

Ко всему, еще есть одна особенность, насколько я знаю, указатель на функцию-член имеет жесткую привязку к типу(классу) в котором эта функция описана, но в этом примере в первом случае вызов (pb->*p) (); эквивалентен B::f()(так как B наследник класса A), т.е. можно сказать, что сработал механизм преобразования имени виртуальной функции в индекс в виртуальной таблице. Для второго присваивания все более проще, при присваивании p = &A::g, а сам p является просто "указателем" на функции-члены класса A и только A, то поэтому и произошел вызов функции A::g(), причем его скорее всего можно интерпритировать как pb->A::g();

P.S. Все вышенаписанное сугубо мое ИМХО :-)

(no subject)

1/2/06 06:52 (UTC)
Posted by (Anonymous)
Вообще-то, это всего лишь мои размышления на тему, почему так работает приведенный пример. Просто пришлось напрячься, чтобы разобраться. Очень понравилось, поскольку когда я разбираю такие примеры я улучшаю знание языка...

(no subject)

1/2/06 07:20 (UTC)
Posted by (Anonymous)
Кстати, вроде А. Александреску рассматривает похожие "фишки" в "Modern C++ Design", точно не помню...

(no subject)

1/2/06 07:52 (UTC)
Posted by (Anonymous)
Кстати, в разделе 15.5(Страуструп) поясняется "в отличие от указателя на переменную или обычную функцию, указатель на член не является просто указателем на область памяти. Он больше соответствует смещению в структуре или индексу в массиве."+(и действительно вывод этого указателя - целое число)+"Сочетание указателя на член с указателем на соответствующий объект дает то, что идентифицирует конкретный член конкретного объекта". Туманно, но для меня все прояснилось до конца...

P.S. наверно я вас достал своими постами, звыняйте... :-)

March 2023

S M T W T F S
   1234
567891011
12131415161718
19202122232425
262728293031 

Page Summary

  • (Anonymous) - fun
Page generated 3/2/26 10:27

Expand Cut Tags

No cut tags