Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 537
  • Last Modified:

virtual inheritance in C++

In the code below what is the purpose of having the TA inherit from a virtual Teacher and virtual Student?
#include <cstdio>
#include <string>
using namespace std;

class Teacher
{
public:
        Teacher( string _name ) : name( _name ) { }
        virtual ~Teacher( ) { }
        virtual string getName( ) { return name; }
protected:
        string name;
};

class Student
{
public:
        Student( string _name ) : name( _name ) { }
        virtual ~Student( ) { }
        virtual string getName( ) { return name; }
protected:
        string name;
};

class TA : virtual public Teacher, virtual public Student
{
public:
        TA( string name ) : Teacher( "Prof. " + name ), Student( name ) { }
        virtual ~TA( ) { }
        virtual string getName( ) { return Teacher::getName( ); }
        string getStudentName( ) { return Student::getName( ); }
        string getTeacherName( ) { return Teacher::getName( ); }
};

Open in new window

0
kuntilanak
Asked:
kuntilanak
  • 3
  • 2
  • 2
  • +2
4 Solutions
 
magicdlfCommented:
This artical might be helping
http://en.wikipedia.org/wiki/Virtual_inheritance
0
 
phoffricCommented:
A TA is a Student and is a Teacher. So, the design is providing multiple inheritance to both classes. As the design progresses, there will be other behaviors added. For example, Student could have doHomework(), and handInHomework(), and partyAllNight(). The Teacher could have gradeHomework(), takeAttendance(). As these methods are added to the base classes, the TA automatically inherits them, which makes sense since these activities are part of a TA's responsibility as both a student and a teacher.

0
 
pchela733Commented:
In case with virtual inheritance you will have only one object of Teacher and only one object of Student.

The "dreaded diamond" refers to a class structure in which a particular class appears more than once in a class's inheritance hierarchy. For example,


 class Base {
 public:
   ...
 protected:
   int data_;
 };
 
 class Der1 : public Base { ... };
 
 class Der2 : public Base { ... };
 
 class Join : public Der1, public Der2 {
 public:
   void method()
   {
      data_ = 1;   bad: this is ambiguous; see below
   }
 };
 
 int main()
 {
   Join* j = new Join();
   Base* b = j;    bad: this is ambiguous; see below
 }
Forgive the ASCII-art, but the inheritance hierarchy looks something like this:


                          Base
                          /  \
                         /    \
                        /      \
                     Der1      Der2
                        \      /
                         \    /
                          \  /
                          Join
Before we explain why the dreaded diamond is dreaded, it is important to note that C++ provides techniques to deal with each of the "dreads." In other words, this structure is often called the dreaded diamond, but it really isn't dreaded; it's more just something to be aware of.

The key is to realize that Base is inherited twice, which means any data members declared in Base, such as data_ above, will appear twice within a Join object. This can create ambiguities: which data_ did you want to change? For the same reason the conversion from Join* to Base*, or from Join& to Base&, is ambiguous: which Base class subobject did you want?

C++ lets you resolve the ambiguities. For example, instead of saying data_ = 1 you could say Der2::data_ = 1, or you could convert from Join* to a Der1* and then to a Base*. However please, Please, PLEASE think before you do that. That is almost always not the best solution. The best solution is typically to tell the C++ compiler that only one Base subobject should appear within a Join object, and that is described next.

[ Top | Bottom | Previous section | Next section | Search the FAQ ]


--------------------------------------------------------------------------------


[25.9] Where in a hierarchy should I use virtual inheritance?
Just below the top of the diamond, not at the join-class.

To avoid the duplicated base class subobject that occurs with the "dreaded diamond", you should use the virtual keyword in the inheritance part of the classes that derive directly from the top of the diamond:


 class Base {
 public:
   ...
 protected:
   int data_;
 };
 
 class Der1 : public virtual Base {
 public:             ^^^^^^^this is the key
   ...
 };
 
 class Der2 : public virtual Base {
 public:             ^^^^^^^this is the key
   ...
 };
 
 class Join : public Der1, public Der2 {
 public:
   void method()
   {
      data_ = 1;   good: this is now unambiguous
   }
 };
 
 int main()
 {
   Join* j = new Join();
   Base* b = j;    good: this is now unambiguous
 }
Because of the virtual keyword in the base-class portion of Der1 and Der2, an instance of Join will have have only a single Base subobject. This eliminates the ambiguities. This is usually better than using full qualification as described in the previous FAQ.

For emphasis, the virtual keyword goes in the hierarchy above Der1 and Der2. It doesn't help to put the virtual keyword in the Join class itself. In other words, you have to know that a join class will exist when you are creating class Der1 and Der2.


                          Base
                          /  \
                         /    \
                virtual /      \ virtual
                     Der1      Der2
                        \      /
                         \    /
                          \  /
                          Join
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
kuntilanakAuthor Commented:
I don't see how this example would be a dreaded diamond case as there's only 2 class derived from one base class...
0
 
phoffricCommented:
I believe the dreaded diamond arises where J is derived from D1 and D2, and both D1 and D2 are derived from B; and, very importantly, B has attributes and B is not abstract (i.e., B can be instantiated). If B is abstract, then it can be thought of as an Interface Class (similar to Java), so even though there may be diamonds in the class diagram, there are not the potential pitfalls of the so-called dreaded diamond.
0
 
magicdlfCommented:
You are right. In this case, you don't have to use the virtual inheritance.
0
 
phoffricCommented:
kuntilanak,
I just realized that by this example you were referring to the author's question, and not the previous post. So, never mind.
0
 
kuntilanakAuthor Commented:
yes....I guess using a normal inheritance will work as well
0
 
pgnatyukCommented:
Remove this keyword (virtual) and compile.
In your case it works the same.
Maybe you are looking for something like that:

class TA : public Teacher, public Student
{
using Student::name;
//..
};

#include <iostream>
using namespace std;

#include <cstdio> 
#include <string> 
using namespace std; 

class Teacher 
{ 
public: 
	Teacher( string _name ) : name( _name ) { } 
	virtual ~Teacher( ) { } 
	virtual string getName( ) { return name; } 
protected: 
	string name; 
}; 

class Student 
{ 
public: 
	Student( string _name ) : name( _name ) { } 
	virtual ~Student( ) { } 
	virtual string getName( ) { return name; } 
protected: 
	string name; 
}; 

class TA : public Teacher, public Student 
{ 
public: 
	TA( string name ) : Teacher( "Prof. " + name ), Student( name ) { } 
	virtual ~TA( ) { } 
	virtual string getName( ) { return Teacher::getName( ); } 
	string getStudentName( ) { return Student::getName( ); } 
	string getTeacherName( ) { return Teacher::getName( ); } 
};

int main()
{
	TA ta("John");
	cout << ta.getName() << endl;
}

Open in new window

0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 3
  • 2
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now