472,342 Members | 1,475 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,342 software developers and data experts.

Abstract Class & Virtual function - Real Implementation?

Hi all,
Though I know the concepts of both abstract class & virtual
function (like derived class pointer pointing to base class...then
calling the function with the pointer...), what is the real
implementation usage of these concepts? Where these concepts will be
used. Please provide some illustration (real-time), so that it can be
easily comprehended.

Thanks,
wittyGuy

Jul 23 '05 #1
4 4103

"WittyGuy" <wi**********@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
Hi all,
Though I know the concepts of both abstract class & virtual
function (like derived class pointer pointing to base class...then
calling the function with the pointer...), what is the real
implementation usage of these concepts? Where these concepts will be
used. Please provide some illustration (real-time), so that it can be
easily comprehended.

Thanks,
wittyGuy


Take a look around you, find me an object which you couldn't classify. In
reality, the whole world around you is classified in some way. Life and
genes, elements and materials, businesses and products, date and time,
energy and work, etc.

The basic idea is that you can classify (no pun intended), contain, upcast,
or provide easy code-expansion for a new object based on its provided
derivative(s).

Common example
A Shape class can be an abstract class to derive a Triangle class, a
Rectangle class and a Circle class. A pure-virtual getArea() member function
in the abstract Shape class requires you to define the getArea() member
function in each of its derivatives. The Circle and the Rectangle, for
example, don't rely on the same getArea() member function to calculate its
area.

Note that this makes OO sense since:
A Triangle is_a Shape
A Rectangle is_a Shape
A Circle is_a Shape

Containers
The benefit is now you can use a container that holds any Shape (an array of
Shapes, a vector, a list, stack, queue, etc). The container needs not track
which shape element is a circle, a triangle or a rectangle. The Shape
container needs only satisfy that each element is a pointer to an existing
Shape derivative.

Shapes* shapes[4]; // a container of pointers to Shape objects

shapes[0] = new Rectangle(10, 10); // (width, length)
shapes[1] = new Circle(5); // (radius)
shapes[2] = new Triangle(7, 6) // (width, length)
shapes[3] = new Circle(22); // (radius)

The element at shapes[0] knows whether its a Circle, Rectangle or Triangle.
The same goes with every other element. The container doesn't care whether
Array[2] is a Triangle, a Rectangle or a Circle. So when you write:

int n = 0;
while ( n < 4 )
{
Array[n++]->getArea();
}

delete [] shapes;

You are calling the appropriate getArea() behaviour for each Shape-type
element in the container (using a vtable). This would not be possible
without the abstract Shape class (a container of what?). Neither would this
be possible without a pure-virtual getArea() member function in Shape (we
need to guarentee that all Shapes have such a member function available).

This ability to contain any derivative-type can be applied to Animals,
Vehicles, Employees, Airplanes, Planets or any other base class you can
think of. Note that the hierarchy need not be so shallow. A Car is a
derivative of Vehicle, a Sportscar is a derivative of Car, hence a Sportscar
can also be an element in a container of Vehicles.

Whats the benefit? All such Vehicles have an engine, a steering wheel and a
gas tank. There is no need to repeatedly insert an engine in all the derived
classes. A Vehicle base class can be composed of an engine and each derived
class needs only invoke the appropriate engine ctor to equip itself with a
particular engine. The startEngine() member function in Vehicle can now
start the engine in any Vehicle. This can save an enormous amount of code
when you consider the variety of motorized vehicle-types out there.

Should a client programmer choose to employ your classes (expand Shape to
provide a pentagon or octagon - expand Vehicle to provide a FireTruck), his
job has been made much easier for both you, the creator, and the client.
You've used a common abstract base class and pure-virtual member functions
which dictates and guarentees the implementation of the new derived entity
in the program.

A quick scan by the client of your base class permits him or her to draw up
the derived FireTruck. The client can add the water pump, the ladder, valves
and whatever he likes or needs. Yet that FireTruck can still be held in any
Vehicle container (highway, FireHouse, bridge, Ferry, Tunnel, etc) and the
original startEngine() member function still works.

The same principles of simplified code reusability can be applied in
virtually any appropriate classification hierarchy.

Jul 23 '05 #2
Hi codigo,
That is a perfect illustration which cleared most of my
doubt regarding abstract class usage. But one concept which still
remains unclear is why is it needed that virtual function (not pure
virtual), to get the base class member function thru derived class
pointer of the object invoked instead using pointer of the base class
object straight-away for invocation?

thanx,
wittyGuy

Jul 23 '05 #3
WittyGuy wrote:

Hi codigo,
That is a perfect illustration which cleared most of my
doubt regarding abstract class usage. But one concept which still
remains unclear is why is it needed that virtual function (not pure
virtual), to get the base class member function thru derived class
pointer of the object invoked instead using pointer of the base class
object straight-away for invocation?


???
Your english is not very clear. At least I cannot figure out
what you are asking about.
The function *is* invoked through a base class pointer. In
codigo's example (when all the syntactic errors are fixed)
all the pointers are base class type pointers.

Here is the compilable, working example again. Note that in
main() the for loop deals with Shape pointers only. Yet the
correct function is invoked.

#include <iostream>

class Shape
{
public:
virtual ~Shape() {}; // needs to be virtual since we are going
// to destroy in a polymorphic way

virtual double GetArea() { return 0.0; } // Could be a pure function if wanted
// since this function should never be called.
// But just in case :-)

virtual const char* Description() { return "Shape"; }
};

class Rectangle : public Shape
{
public:
Rectangle( double Width, double Height )
: m_Width( Width ), m_Height( Height )
{}

virtual double GetArea() { return m_Width * m_Height; }
virtual const char* Description() { return "Rectangle"; }

protected:
double m_Width;
double m_Height;
};

class Circle : public Shape
{
public:
Circle( double Radius )
: m_Radius( Radius )
{}

virtual double GetArea() { return m_Radius * m_Radius * 3.1415926; }
virtual const char* Description() { return "Circle"; }

protected:
double m_Radius;
};

int main()
{
Shape* Shapes[2];

Shapes[0] = new Rectangle( 3.0, 5.0 );
Shapes[1] = new Circle( 4.0 );

for( int i = 0; i < 2; ++i ) {
std::cout << i << ": I am a "
<< Shapes[i]->Description()
<< " and my area is "
<< Shapes[i]->GetArea()
<< "\n";
}

delete Shapes[0];
delete Shapes[1];
}

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 23 '05 #4

"WittyGuy" <wi**********@gmail.com> wrote in message
news:11*********************@f14g2000cwb.googlegro ups.com...
Hi codigo,
That is a perfect illustration which cleared most of my
doubt regarding abstract class usage. But one concept which still
remains unclear is why is it needed that virtual function (not pure
virtual), to get the base class member function thru derived class
pointer of the object invoked instead using pointer of the base class
object straight-away for invocation?

thanx,
wittyGuy


You could have used a pure virtual instead of a virtual function. In many
cases this makes sense. A pure virtual getArea() member function requires
that any Shape derivative implement getArea(). It also prevents
instantiation of an underived Shape object.

You could also use a virtual getArea() in the Shape class and protect the
ctor as an alternative (to prevent the instantiation of an underived Shape
object).

The difference between using either a pure-virtual or virtual is that with a
pure-virtual member function, you can't directly call the base's
pure-virtual getArea() and the Shape class is abstract without having to
protect its ctor. However, the vtable mechanism doesn't prevent you from
calling Shape::getArea() from a Circle or Triangle. The language has the
flexibility to meet your needs one way or another.

Lets store the area in an abstract Shape class. Lets calculate the area in
the Shape ctor invocations (in the derived initialization lists).

#include <iostream>
using std::cout;

class Shape
{
const double m_area;
public:
Shape(double a) : m_area(a) { }
virtual ~Shape() {};
virtual double getArea() const = 0
{
return m_area;
}
}; // class Shape

class Circle : public Shape
{
double m_radius;
public:
Circle(double r)
: m_radius(r),
Shape(r * r * 3.1416) { }
~Circle() { }
double getArea() const
{
cout << "Circle's area is ";
return Shape::getArea();
}
}; // class Circle

class Rectangle : public Shape
{
double m_width;
double m_height;
public:
Rectangle(double w, double h)
: m_width(w),
m_height(h),
Shape(w * h) { }
~Rectangle() { }
double getArea() const
{
cout << "Rectangle's area is ";
return Shape::getArea();
}
}; // class Rectangle

class Triangle : public Shape
{
double m_width;
double m_height;
public:
Triangle(double w, double h)
: m_width(w),
m_height(h),
Shape((w * h)/2) { }
~Triangle() { }
double getArea() const
{
cout << "Triangle's area is ";
return Shape::getArea();
}
}; // class Triangle

int main()
{
Shape* shapes[3];

shapes[0] = new Circle(2.5);
shapes[1] = new Rectangle(5.0, 2.0);
shapes[2] = new Triangle(5.0, 2.0);

for( int i = 0; i < 3; ++i )
{
cout << "shapes[" << i << "]: ";
cout << shapes[i]->getArea();
cout << std::endl;
}

delete shapes[0];
delete shapes[1];
delete shapes[2];

return 0;
} // main()

******
output:

shapes[0]: Circle's area is 19.635
shapes[1]: Rectangle's area is 10
shapes[2]: Triangle's area is 5


Jul 23 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
by: Medi Montaseri | last post by:
Hi, Given a collection of similar but not exact entities (or products) Toyota, Ford, Buick, etc; I am contemplating using the Abstraction pattern...
9
by: Anon Email | last post by:
Hi people, I'm learning about header files in C++. The following is code from Bartosz Milewski: // Code const int maxStack = 16; class...
8
by: Dev | last post by:
Hello, Why an Abstract Base Class cannot be instantiated ? Does anybody know of the object construction internals ? What is the missing...
18
by: Bradley | last post by:
I'm trying to determine if there's a general rule for when an Interface should used vs. an Abstract Class. Is there any design advantage to using...
7
by: tron.thomas | last post by:
Please consider the following code: class Abstract { public: virtual ~Abstract() {} virtual void Method() = 0; }; class Concrete : public...
6
by: Alden Pierre | last post by:
Hello, http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7 As per the link above it's wise to have a virtual deconstructor...
0
by: mailforpr | last post by:
Hi. Let me introduce an iterator to you, the so-called "Abstract Iterator" I developed the other day. I actually have no idea if there's...
4
by: David Zha0 | last post by:
Hi, "when we call a virtual method, the runtime will check the instance who called the method and then choose the suitable override method, this...
17
by: Jess | last post by:
Hello, If I have a class that has virtual but non-pure declarations, like class A{ virtual void f(); }; Then is A still an abstract class?...
0
better678
by: better678 | last post by:
Question: Discuss your understanding of the Java platform. Is the statement "Java is interpreted" correct? Answer: Java is an object-oriented...
0
by: teenabhardwaj | last post by:
How would one discover a valid source for learning news, comfort, and help for engineering designs? Covering through piles of books takes a lot of...
0
by: CD Tom | last post by:
This only shows up in access runtime. When a user select a report from my report menu when they close the report they get a menu I've called Add-ins...
0
by: Naresh1 | last post by:
What is WebLogic Admin Training? WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge...
0
jalbright99669
by: jalbright99669 | last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made...
0
by: antdb | last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine In the overall architecture, a new "hyper-convergence" concept was...
0
by: Matthew3360 | last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function. Here is my code. ...
2
by: Matthew3360 | last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...
0
by: Arjunsri | last post by:
I have a Redshift database that I need to use as an import data source. I have configured the DSN connection using the server, port, database, and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.