Путаница с тем, как вызывается виртуальная функция производного класса - PullRequest
0 голосов
/ 25 декабря 2011

В приведенном ниже коде я не могу понять, как вызывается виртуальный метод производного класса. Кроме того, может ли кто-нибудь предложить источник, в котором понятия виртуальной функции схематически объясняются очень простым подходом.

class Base1
{
  virtual void fun1() { cout << "Base1::fun1()" << endl; }
  virtual void func1() { cout << "Base1::func1()" << endl; }
};


class Base2 
{
  virtual void fun1() { cout << "Base2::fun1()" << endl; }
  virtual void func1() { cout << "Base2::func1()" << endl; }
};


class Base3 
{
    virtual void fun1() { cout << "Base3::fun1()" << endl; }
    virtual void func1() { cout << "Base3::func1()" << endl; }
};

class Derive : public Base1, public Base2, public Base3
{

public:

  virtual void Fn()
  {
    cout << "Derive::Fn" << endl;
  }

  virtual void Fnc()
  {
    cout << "Derive::Fnc" << endl;
  }
};


typedef void(*Fun)(void);

int main()
{
  Derive obj;
  Fun pFun = NULL;

  // calling 1st virtual function of Base1
  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);
  pFun();

  // calling 2nd virtual function of Base1
  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
  pFun();

  // calling 1st virtual function of Base2
  pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+0);

  pFun();

  // calling 2nd virtual function of Base2

  pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+1);
  pFun();

  // calling 1st virtual function of Base3
  pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+0);
  pFun();

  // calling 2nd virtual function of Base3
  pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+1);

  pFun();

  // calling 1st virtual function of Drive
  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);
  pFun();

  // calling 2nd virtual function of Drive
  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
  pFun();

  return 0;
}

Ответы [ 2 ]

5 голосов
/ 25 декабря 2011

Диаграмма наследования выглядит следующим образом:

Base1  Base2  Base3

  \      |      /
   \     |     /
    \    |    /
     \   |   /

      Derived

Нет однозначной функции Derived::func1().Более того, ключевое слово virtual - это красная сельдь, потому что Derived на самом деле ничего не перекрывает.Так что единственный вопрос - как вызывать различные базовые функции.Вот как:

Derived x;

// x.func1(); // Error: no unambiguous base function

x.Base1::func1();
x.Base2::func1();
x.Base3::func1();

История была бы совершенно иной, если бы вы на самом деле переопределили func1() в Derived.

0 голосов
/ 25 декабря 2011

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

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

http://www.codeproject.com/KB/cpp/FastDelegate.aspx

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