Saturday 31 October 2015

-SPECIAL PROBLEMS ON INHERITANCE(click here to view)

THIS POST IS BASICALLY EXPLAINING THE SPECIAL PROBLEMS IN INHERITANCE..will keep updating 



The diamond problem

The diamond problem occurs when two superclasses of a class have a common base class. For example, in the following diagram, the TA class gets two copies of all attributes of Person class, this causes ambiguities.




For example, consider the following program.
#include<iostream>
using namespace std;
class Person {
   // Data members of person
public:
    Person(int x)  { cout << "Person::Person(int ) called" << endl;   }
};
class Faculty : public Person {
   // data members of Faculty
public:
    Faculty(int x):Person(x)   {
       cout<<"Faculty::Faculty(int ) called"<< endl;
    }
};
class Student : public Person {
   // data members of Student
public:
    Student(int x):Person(x) {
        cout<<"Student::Student(int ) called"<< endl;
    }
};
class TA : public Faculty, public Student  {
public:
    TA(int x):Student(x), Faculty(x)   {
        cout<<"TA::TA(int ) called"<< endl;
    }
};
int main()  {
    TA ta1(30);
}


OUTPUT:


Person::Person(int ) called
Faculty::Faculty(int ) called
Person::Person(int ) called
Student::Student(int ) called
TA::TA(int ) called

In the above program, constructor of ‘Person’ is called two times. Destructor of ‘Person’ will also be called two times when object ‘ta1′ is destructed. So object ‘ta1′ has two copies of all members of ‘Person’, this causes ambiguities. The solution to this problem is ‘virtual’ keyword. We make the classes ‘Faculty’ and ‘Student’ as virtual base classes to avoid two copies of ‘Person’ in ‘TA’ class. For example, consider the following program.
#include<iostream>
using namespace std;
class Person {
public:
    Person(int x)  { cout << "Person::Person(int ) called" << endl;   }
    Person()     { cout << "Person::Person() called" << endl;   }
};
class Faculty : virtual public Person {
public:
    Faculty(int x):Person(x)   {
       cout<<"Faculty::Faculty(int ) called"<< endl;
    }
};
class Student : virtual public Person {
public:
    Student(int x):Person(x) {
        cout<<"Student::Student(int ) called"<< endl;
    }
};
class TA : public Faculty, public Student  {
public:
    TA(int x):Student(x), Faculty(x)   {
        cout<<"TA::TA(int ) called"<< endl;
    }
};
int main()  {
    TA ta1(30);
}


PROGRAM:



Person::Person() called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called




Delegating to a sister class

A powerful technique that arises from using virtual inheritance is to delegate a method from a class in another class by using a common abstract base class. This is also called cross delegation. Let's assume we have a similar scenario like in the diamond example, with small changes. Suppose the write() method in transmitter class needs to access the read() method from receiver for the radio to work (this is kind of a weird behavior, but let's take it for the sake of illustration) :


class storable 
{
        public:
        storable(const char*);
        virtual void read()=0; //this becomes pure virtual making storable an abstract
        virtual void write(); //class
        virtual ~storable();
        private:
        ....
}

class transmitter: public virtual storable 
{
        public:
        void write()
        {
                read();
                ....
        }
} 

class receiver: public virtual storable
{
        public:
        void read();
}

class radio: public transmitter, public receiver
{
        public:
        ...
}

int main()
{
        radio *rad = new radio();
        receiver *r1 = rad;
        transmitter *r2 =rad;

        rad->write();
        r1->write();
        r2->write();
        return 1;
}



Because of virtual inheritance, when the write() function from the transmitter class is called, the method read() from the receiver class gets called (as you may have noticed, the transmitter class doesn't have a read() function). In the above hierarchy we can instantiate only the radio class because transmitter and receiver are abstract due to virtual inheritance.

No comments:

Post a Comment