Two Base Classes, One display()
A student designs a school library system in C++. Class Member has a protected string name and a public void display(). StudentMember and TeacherMember inherit publicly from Member, add roll and empId respectively, and each defines its own display(). A new class GuestMember represents a visiting parent who may borrow books like a student and reserve a lab like a teacher. The student declares class GuestMember : public StudentMember, public TeacherMember. Compiling GuestMember g; g.display(); gives an ambiguity error. The student also finds that g.name is ambiguous and that constructing a GuestMember runs the Member constructor twice. The teacher says multiple inheritance is not automatically wrong, but this design may be. The class must still allow a GuestMember to be passed to a function void print(Member& m), and the student has one week before the practical exam. The student wants to know whether virtual inheritance alone solves every symptom.
1. Diagnose the three symptoms: ambiguous g.display(), ambiguous g.name, and two Member constructor calls. Which are caused by the diamond, and which by name lookup?
Read the worked answer
GuestMember inherits from both StudentMember and TeacherMember, and each of those inherits non-virtually from Member. The object therefore contains two Member subobjects. That single fact explains the two Member constructor calls and the ambiguity of g.name: name lookup finds two different name members, one in each base branch. g.display() is ambiguous for a related but distinct reason: lookup finds StudentMember::display and TeacherMember::display in two different base classes, so the call has no unique best match. Virtual inheritance of Member merges the two Member subobjects into one, removing the duplicate name and the double construction. It does not automatically merge the two display functions, because those are separate overrides in the two branches; a using declaration or an explicit override in GuestMember is still needed to disambiguate.
2. Propose one design that keeps multiple inheritance and one that avoids it. Give a trade-off for each.
Read the worked answer
Keep multiple inheritance: make Member a virtual base (class StudentMember : virtual public Member and similarly for TeacherMember), then define GuestMember : public StudentMember, public TeacherMember and add an explicit display() or a using declaration. Trade-off: one shared Member and genuine substitutability for both roles, but virtual-base construction is more complex and the most-derived class must initialize Member. Avoid multiple inheritance: use composition-GuestMember contains a Member object plus two role objects, or a single Member with a role enum and capability flags. Trade-off: no diamond and simpler constructors, but a GuestMember is no longer a StudentMember or TeacherMember, so role checks become runtime rather than type-based. A middle design uses abstract role interfaces with no data, which avoids the data diamond while keeping polymorphic roles.
3. Can GuestMember be passed to void print(Member& m)? Explain under both non-virtual and virtual inheritance, and state one constructor consequence of the virtual version.
Read the worked answer
Under non-virtual inheritance, GuestMember has two Member subobjects, so the conversion to Member& is ambiguous and the call does not compile. Under virtual inheritance, there is one shared Member subobject, so the conversion is unambiguous and the call works. The constructor consequence is that the most-derived class is responsible for initializing the virtual base: GuestMember's constructor must initialize Member directly (for example, GuestMember(...) : Member(name), StudentMember(...), TeacherMember(...) { }). Initializations of Member inside StudentMember and TeacherMember are ignored when those classes are used as intermediate bases of a most-derived GuestMember.