[C/C++] virtual inheritance

Language/C&C++ 2007.03.24 22:18
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

At first, see
 virtual inheritance in wikipedia to know about virtual inheritance.

There are lots of articles about this. So, I am adding 'Real' example tested on "MSVC2005 Express".
- Don't use 'debug watch' of VC. Sometimes it show wrong information!.
(Note: C++ standard doens't define anything about the way of implementing dynamic polymorphism. So, results are dependent on compiler.)

==================================
Non-Virtual Inheritance
class Animal
{
  virtual void Eat(){};
  int animal;
};

Animal
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Mammal : public Animal
{
  virtual void Run(){};
  int mammal
};

Mammal
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+     Mammal::Run()
  |   int animal    |
  +-----------------+
  |   int mammal    |
  +-----------------+

class Winged : public Animal
{
  virtual void Flap(){};
  int winged
};

Winged
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+     Winged::Flap()
  |   int animal    |
  +-----------------+
  |   int winged    |
  +-----------------+

class Bat : public Mammal, public Winged
{
  virtual void Hang(){};
};

Bat
  +-----------------+
  |   __vfptr       |---> Animal::Eat() (*1) [from Mammal]
  +-----------------+     Mammal::Run()
  |   int animal    |     Bat::Hang()
  +-----------------+
  |   int mammal    |
  +-----------------+
  |   __vfptr       |---> Animal::Eat() (*2) [from Winged]
  +-----------------+     Winged::Flap()
  |   int animal    |
  +-----------------+
  |   int winged    |
  +-----------------+

(Address of (*1) and (*2) is different.)

======================================
Virtual Inheritance

class Animal
{
public:
  Animal():animal(){}
  virtual void Eat(){};
  int animal;
};

Animal
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Mammal : public virtual Animal
{
public:
  Mammal():mammal(){}
  virtual void Run(){};
  int mammal;
};

Mammal
  +-----------------+
  |   __vfptr       |---> Mammal::Run()
  +-----------------+
  |   ???????????   |
  +-----------------+
  |   int mammal    |
  +-----------------+
  |    __vfptr      |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Winged : public virtual Animal
{
public:
  Winged():winged(){}
  virtual void Flap(){};
  int winged;
};

Winged
  +-----------------+
  |   __vfptr       |---> Winged::Flap()
  +-----------------+
  |   ???????????   |
  +-----------------+
  |   int winged    |
  +-----------------+
  |    __vfptr      |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Bat : public Mammal, public Winged
{
  virtual void Hang(){};
};

Bat
  +-----------------+
  |   __vfptr       |---> Mammal::Run()
  +-----------------+     Bat::Hang()
  |   ??????????    |
  +-----------------+
  |   int mammal    |
  +-----------------+
  |   __vfptr       |---> Winged::Flap()
  +-----------------+
  |   ??????????    |
  +-----------------+
  |   int winged    |
  +-----------------+
  |    __vfptr      |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+
===============================

NOTE: I have no idea what "?????" means. I think this is only for internal use of VC.

Here is view of this.

"---." : reference member (p.xxx)
"--->" : pointer member (p->xxx)

Non-virtual inheritance
  bat
  |----. Mammal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415770) --- (*1)
  | | | |----> Animal::eat(void)
  | | | |----> Mammal::setHairColor(void)
  |
  |----. WingedAnimal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415760) --- (*2)
  | | | |----> Animal::eat(void)
  | | | |----> WingedAnimal::flap(void)

Virtual inheritance case
  bat
  |----. Mammal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415788) --- (*3)
  | | | |----> Animal::eat(void)
  | |----. __vfptr
  | | |----> Mammal::setHairColor(void)
  |
  |----. WingedAnimal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415788) --- (*4)
  | | | |----> Animal::eat(void)
  | |----. __vfptr
  | | |----> WingedAnimal::flap(void)

We should focus on that pointed address indicated at (*1) and (*2) is different, but the one at (*3) and (*4) is same - actually, it's not separated entity, it's same one. That is, there is one vftable for Animal class.

Now we can know the way of virtual inheritance.

신고
tags : ,
Trackback 0 : Comment 0

티스토리 툴바