A stop at the Inheritance station

Here we are at the station of Inheritance!


Typically in inheritance, there are two classes. Let us consider the analogy of parents and children. A child has few common traits like the same color of eyes, nose and ear shapes, etc same as their parents. The child has some common genes of their parent, it implies they inherit traits from there parents. 



Following the example, the parent represents parent class or base class and the child represents the derived class. When a class inherits from another, it brings forward all the data that is being shared by the parent.


Here is an example,
class derived_class : visibility-mode base_class
{
// body of the derived class.
}


Where, 

derived_class: It is the name of the derived class. 



visibility mode: The visibility mode specifies whether the features of the base class are publicly inherited or privately inherited. It can be public or private. 


base_class: It is the name of the base class. 


When the base class is privately inherited by the derived class, public members of the base class become the private members of the derived class. Therefore, the public members of the base class are not accessible by the objects of the derived class only by the member functions of the derived class. 

When the base class is publicly inherited by the derived class, public members of the base class also become the public members of the derived class. Therefore, the public members of the base class are accessible by the objects of the derived class as well as by the member functions of the base class.



In C++ the default visibility mode is private. The private members of the base class are never inherited. Just to remind, Visibility modes can be classified into three categories. 

  • Public: When the member is declared as public, it is accessible to all the functions of the program.
  • Private: When the member is declared as private, it is accessible within the class only.
  • Protected: When the member is declared as protected, it is accessible within its own class as well as the class immediately derived from it.
Refer to the following table for visibility clearance. 

public, protected and private Inheritance | Object-Oriented ...


Let us move to some types of inheritance. 

  • Single inheritance is defined as the inheritance in which a derived class is inherited from the only one base class.
  • Multiple inheritance is the process of deriving a new class that inherits the attributes from two or more classes. 
  • Hybrid inheritance is a combination of more than one type of inheritance.
  • Hierarchical inheritance is defined as the process of deriving more than one class from a base class. 
  • Multilevel inheritance is the process of having inheritance in more than two levels. 
You can now guess the type of inheritance we have used in this system! Want to learn some advanced concepts? Here are the -

Multi-methods

A multi-method is a method that is chosen according to the dynamic type of more than one object. They tend to be useful when dealing with interactions between two objects. As we have seen, virtual functions allow the run-time resolution of a method based on the dynamic type of the receiving object. However, a parameter to a function can only be matched according to its static type. This limits us to determine which method to call to the dynamic type of one object (the object upon which the method is invoked). C++ has no built-in support for multi-methods. Other languages, such as CLOS, do have support for these. Assume we have an intersect method which tells us if two shapes intersect: 



class Shape { 

... 

virtual bool intersect(const Shape *s) = 0; 

... 

}; 


class Rectangle : public Shape { 
... 
virtual bool intersect(const Shape *s); 
... 
}; 

class Circle : public Shape { 
... 
virtual bool intersect(const Shape* s); 
... 
}; 

It doesn't make sense to see if a Rectangle or a Circle intersects a Shape. So we immediately see the need to provide more specialized methods: 

class Shape {
... 
virtual bool intersect(const Shape *s) = 0; 
virtual bool intersect(const Circle *c) = 0; 
virtual bool intersect(const Rectangle *r) = 0; 
... 
}; 

class Rectangle : public Shape { 
... 
virtual bool intersect(const Shape *s); // illustrated below 
virtual bool intersect(const Circle *c); // Checks circle/rectangle 
virtual bool intersect(const Rectangle *r); // Checks rectangle/rectangle 
... 
}; 

class Circle : public Shape { 
... 
virtual bool intersect(const Shape *s); // wrapper implementation below 
virtual bool intersect(const Circle *c); // Checks circle/circle 
virtual bool intersect(const Rectangle *r); // Checks rectangle/circle 
... 
}; 

Note that we have to declare many methods that should never be called in order to prevent the hiding of methods through overloading. 
If we allocate a Circle and a Rectangle whose static types are Shape *, we’re in for a few surprises:

Shape* circle = new Circle(...); // upcast to Shape 

Shape* rectangle = new Rectangle(...); // upcast to Shape 

circle->intersect(rectangle); // Calls Circle::intersect(Shape*)

rectangle->intersect(circle); // Calls Rectangle::intersect(Shape*) 



We’re getting one level of reification through the use of virtual functions. As it is mentioned let us revise virtual functions.


Virtual function

  • ·A C++ virtual function is a member function in the base class that you redefine in a derived class. It is declared using the virtual keyword.
  • It is used to tell the compiler to perform dynamic linkage or late binding on the function.
  • There is a necessity to use the single pointer to refer to all the objects of the different classes. So, we create the pointer to the base class that refers to all the derived objects. But, when the base class pointer contains the address of the derived class object, it always executes the base class function. This issue can only be resolved by using the 'virtual' function.
  • A 'virtual' is a keyword preceding the normal declaration of a function.
  • When the function is made virtual, C++ determines which function is to be invoked at the runtime based on the type of the object pointed by the base class pointer.


To be in the flow, here are some rules to be followed. 

  • Virtual functions must be members of some classes.
  • Virtual functions cannot be static members.
  • They are accessed through object pointers.
  • They can be a friend of another class.
  • A virtual function must be defined in the base class, even though it is not used.
  • The prototypes of a virtual function of the base class and all the derived classes must be identical. If the two functions with the same name but different prototypes, C++ will consider them as the overloaded functions.
  • We cannot have a virtual constructor, but we can have a virtual destructor



With this note, we have completed our super technical break. Time to move away. Let us visit the next station! 



- Sampada Petkar (K 62)


Comments

Post a Comment

Popular posts from this blog

Do you have a ticket?

It's moderator's Office

Dynamic Memory Allocation in C++