c++ - virtual inheritance_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > c++ - virtual inheritance

c++ - virtual inheritance

 2012/10/15 10:40:47  joe.bq.wang  程序员俱乐部  我要评论(0)
  • 摘要:Aswehavediscussedinthepost-c++typeofinheritance,wehavecoveredprivateinheritance(a.k.a)implementationinheritance,protectedinheritanceandpublicinheritance(a.k.atypeinheritance).Inthistopicwearegoingtodiscussvirutalinheritance.However
  • 标签:c++

As we have discussed in the post - c++ type of inheritance, we have covered private inheritance (a.k.a ) implementation inheritance, protected inheritance and public inheritance (a.k.a type inheritance). In this topic we are going to discuss virutal inheritance.

?

However, called virtual inheritance, it does not have close relationship with the private/protected/public inheritance. virtual inheritance is often used in the cases where multiple inheritance hierarichy is used.?

?

?

For our discussion, let's first see an class hierarchy.?

?

?

hierarchy_example 1

               ZooAnimal                                 Endangered
            /            \                                /
         -V-              -V-                            /
        /                   \                           /
     Bear                   Racoon                    /
           \                   \                     /
            ------------\       \                   /
                         \       \       --------- /
                          \       \     /    
                          ------  Panda

?

ZooAnimal is a virtual base class of Raccon and Bear.?

?

Before we dive into the virtual inheritance, let's first examine the problem without virtual base/inheritance.

?

?

?

C++ is a language which supports multiple inheritance. We have learned that?when a class subclass another class, the super class become a subobject of the derived class, suppose?if through multiple inheritance tree, a class appears twice on both side, then it has some problem?this has two implications

? 1. it waste spaces

? 2. a more serious problem is ambiguity, which member method/data object to call?

?

virtual inhertiance is just to address the issue we have identified earlier. ?under virtual inheritance:??there is only a single, shared base class subobject is inherited regardless of how many times the base class occurs within the derivation hierarchy.

?

so the importance of virtual inheritance under multiple inhertiance is said, let see some code examples.?

?

?

/*
* ZooAnimal to support a void paramter constructor
*/
class ZooAnimal {

public:
	ZooAnimal(string name, bool onExhibit, string fam_name) : _name(name), _onExhibit(onExhibit), _fam_name(fam_name) {}
        // We will see under what situation we need a void parameter ctor
	// ZooAnimal() : _name(NULL), _onExhibit(false), _fam_name(NULL) {}

	virtual ~ZooAnimal();
	virtual ostream& print (ostream &) const; 
	string name() const { return _name; } 
	string family_name() const { return _fam_name; } 
private:
protected:
	bool _onExhibit;
	string _name;
	string _fam_name;
} ;
? then the Bear?
class Bear: public virtual ZooAnimal { 
public:
	enum DanceType { two_left_feet, macarena, fandango, waltz } ;
	Bear(string name, bool onExhibit= true) : ZooAnimal(name, onExhibit, "Bear") , _dance(two_left_feet)
	{}
	virtual ostream & print(ostream& ) const; 
	void dance(DanceType );
private:
protected:
	DanceType _dance;
};
?then The Raccoon
class Raccoon : virtual public ZooAnimal { 
public:
	Raccoon(string name, bool onExhibit = true) : ZooAnimal(name, onExhibit, "Raccoon"), _pettable(false) {}
	virtual ostream& print(ostream& ) const;
	bool pettable() const { return _pettable; }
	void pettable(bool petval) { _pettable = petval; } 
private:
protected:
	bool _pettable;
};
? followed by Endangered
class Endangered
{
public:
	enum CriticalLevel { critical, high, low, trivial };
	enum EndangeredCause { environment, population } ;


	Endangered(EndangeredCause cause, CriticalLevel level) : _cause(cause), _level(level) { }
private:
protected:
	CriticalLevel _level;
	EndangeredCause _cause;
};
?Last is the Panda?
class Panda : public Bear, public Raccoon, public Endangered 
{
public: 
	Panda(string name, bool onExhibit = true) ;
	virtual ostream& print(ostream &) const; 

	bool sleeping () const { return _sleeping; } 

private:
protected:
	bool _sleeping;
};
?

Special Initialization Semantics

You may have noticed that the Pand class does not have the constructor defined. ?The initialization in virtual base cases is different from what it is in single hierarchy case. ?Let's examine our Panda case.?
when a Panda object is initialized , (1) the explicit nvocation of the ZooAnimal constructor within Raccoon and Bear are no loger executed??during the execution and (2) the ZooAnimal constructor is invoked with the arguments specified for the ZooAnimal constructors in the initialization list of the Panda constructor,
within Panda, both the Bear and Raccoon classes serve as intermediates rather as the most derived class, As an intermediate derived class, direct invocation of all virtual ?base class constructor are suppresessed automatically. Were panda subsequently derived from, then Panda itself would become ?an inermediate class of the derived class object,?

with this in mind, let' s see the constructor code below.?
Panda::Panda(string name, bool onExhibit) : ZooAnimal (name, onExhibit, "Panda"),
											Bear(name, onExhibit),
											Raccoon(name, onExhibit), 
											Endangered(Endangered::environment, 
											Endangered::critical),
											_sleeping(false)
{
}
? We may come back to order of virtual base initialization, but first let's first ?check the code of ctor, Bear and Raccoon just simply pass on/carry the name and onExhibit arguments to its base class when they are serving as the intermediate derived class . So, there is excessive call, a different design, by modifying the ctor of Bear/Raccon is as follow?

class Bear: public virtual ZooAnimal { 
public:

	Bear(string name, bool onExhibit= true) : ZooAnimal(name, onExhibit, "Bear") , _dance(two_left_feet)
	{}
protected:
	// when an intermediate derived class
	Bear() : _dance( two_left_feet) {}
        // rest are the same..
};
?you may modify the ZooAnimal slight bit to have an empty protected argument list constructor?
class ZooAnimal {
protected:
	ZooAnimal() : _name(NULL), _onExhibit(false), _fam_name(NULL) {}

} ;
?you can do the same to Raccoon, after the modification, you can modify the ctor of Panda as such .?
Panda::Panda(string name, bool onExhibit) : ZooAnimal (name, onExhibit, "Panda"),
											Endangered(Endangered::environment, 
											Endangered::critical),
											_sleeping(false)
{
}
? Neater, isn't it??

Construcotr and destructor order

Given a inheritance tree, where virtual base classes can appear in more than one inheritance subtree.
So, as usual, I will give a inheritance tree is as followe to allow us to describe what we can achieve.
/** 
* hierarchy_example 2
*
*    Character      ZooAnimal      ToyAnimal
*       ^               ^             ^
*       |               v            v
*       |               |           /
*    RockCharacter   Bear          /
*          ^            ^         /
*          |            |        /
*          \           /   --- -
*            \       /   /      
*             TdeddyBear
*
*/

/*
*  there is a  basic rule in terms the order of the Constructor and Destructor Order
*   Virtual base classes are always constructed prior to to nonvirutal base classes regardless where they appear in the inheritance hierarchy. 
*  Let's see the example above, we are going to illustrate the discussion we have seen before.
* 
*/
class Character {} ;
class BookCharacter : public Character { };
class ToyAnimal { } 
class TeddyBear : public BookCharacter, public Bear, public virtual ToyAnimal 
{

};
? The immediate base classes are examined in the order of their declaration for the presence of virutal base calsses.
In our example, the inheritance ?subtree of BookCharacter is examined first, then that of Bear, ?and finally that of ToyAnimal, Each subtreee is examined in depth first, tat is the sarch begins ??first with the root classes and moves down. For the BookCharacter subtree, first Charcter, then BookCharacter are examined . For the Bear Subtree, first ZooAnimal, then Bear are examined. ??
The order of virtual base class constructor are nvoked. the nonvirtual base classes constructors are invoked in the order of declaration.: BookCharacter then Bear. Prior to execution of the BookCharacter?, its base Character constructor is invoked.? ? ?Given the declaration?
   TeddyBear Paggington;
it will call the consturctor as follow.?
  ZooAnimal();
 ToyAnimal();
  Character()
 BookCharacter()
 Bear();
 TeddyBear()
?

发表评论
用户名: 匿名