You are here:

C++/Function overriding

Advertisement


Question

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

Followup To

Question -
Sir,

 How can i impliment the following.

I want to call an overrided function of the base class using an object of the derrived class.Is it possilbe.If so how?

Please help me out

Answer -
I shall try but I am not at all sure what it is you are trying to do.

There three things I can think of:

- You have an overridden function in the derived class, an object of that class and you wish to call this version of the overridden function. This seems straight forward enough: You just make a call to the overridden version implemented by the derived class as usual.

- More likely is that you have an overridden function, and from the overridden function in the derived class or one of its other member functions you wish to call the base class implementation of the virtual function. This is a common thing to want to do, and the way to do it is to call the base class function non-virtually. You can do this by qualifying the function name with the name of the base class:

   class Base
   {
   public:
       virtual ~Base() {}

       virtual void fn() const;
   };

   void Base::fn() const
   {
       std::cout << "Base::fn() called\n";
   }

   class Derived : public Base
   {
   public:
       virtual void fn() const;
   };

   void Derived::fn() const
   {
       std::cout << "Derived::fn() called\n";

   // #### Call Base::fn implementation ####
       Base::fn();
   }

Note that for this to work Base::fn cannot be private otherwise sub-classes will have no rights to call it.

- Third is that you have an object of the derived class but wish to call the base class implementation of the overridden function. This can be done by slicing the derived object into a base object, and can be achieved by copying the derived object to a base object. Using the example above:

   Derived d;
   d.fn();      // Calls Derived::fn()

   Base b(d);
   b.fn();      // Calls Base::fn()

More often than not doing this sort of thing is not what is required and occurs by accident. One classic way to get this effect is to pass a polymorphic object to functions as its base type by value:

   void SliceIt( Base const b )
   {
       b.fn();    // Always calls Base::fn()  
   }

Of course to prevent this slicing effect and maintain polymorphic behaviour we pass polymorphic objects by reference (or pointer) to their base type:

   void DoNotSliceIt( Base const & b )
   {
       b.fn();
   }

If none of these covers your problem then I apologise for being so dense, and please post a follow up question explaining in more detail what you are trying to do.

Sir please consider the following code

Class A
{
......intialisation.......

virtual void fun1()
{
cout<<"From base class"<<endl;
}
virtual ~A() {}
}
Class B:public Class A
{
............intialisation......
void fun1()
{
cout<<"From derreved class";
}
virtual ~B() {}
}
main()
{
 A objA=new A();
 B objB=new B();
 objA.fun1();//prints :From base class
 objB.fun1();//prints :From derrived class
 return 0;
}
My question
1.Is it possible to print output as "From base class" using objB.If so how?
2.Is it possible to print output as "From derrived class" using objA.If so how?
3.Weather it can be implimentd using pointer of the type Class or a pointer to  a class  

Answer
First I should point out that the example code you show is not C++ as I know it. The keyword class, like all C and C++ keyword is case sensitive and is _not_ capitalised. Class definitions are terminated by a semicolon:

class X
{
// ...
};

These may just be typos on your part, especially if like me you use a ‘helpful’ (not) Word processor to type up your questions that tries to capitalise first characters of each sentence! More serious is that you seem to think that new returns an object by value, and/or that class objects are reference types, as in other languages such as Java or C#. In C++ new returns a _pointer_ to the object:

 A * pointer_to_objA=new A;
 B * pointer_to_objB=new B;

Also you do not need to specify the () for the constructor’s parameters if using a default constructor. Because we are using pointers it means you have to use the arrow operator to access members:

 pointer_to_objA->fun1();//prints :From base class
 pointer_to_objB->fun1();//prints :From derived class

Also unlike languages such as Java and C#, C++ has _no_ garbage collection so you have to delete dynamically created objects yourself:

 delete pointer_to_objA;
 delete pointer_to_objB;

Other things wrong are use of class when specifying base classes, not specifying class members you wish assessable by others as public, and not specifying int as the return type for main (this would be legal for C but not C++). The corrected code, which I built and ran under Microsoft VC++ 2005 (aka VC++ 8) looks like so:

class A
{
public:
   virtual void fun1()
   {
       cout<<"From base class\n";
   }

   virtual ~A() {}
};

class B : public A
{
public:
   void fun1()
   {
       cout<<"From derived class\n";
   }

   // Not really necessary as compiler provided
   // default will ‘inherit’ the virtuality for us
   virtual ~B() {}
};

int main()
{
   A * pointer_to_objA=new A;
   B * pointer_to_objB=new B;
   pointer_to_objA->fun1(); // prints: From base class
   pointer_to_objB->fun1(); // prints: From derived class

   delete pointer_to_objA;
   delete pointer_to_objB;
   return 0;    // Not really necessary for main and main only.
}

An alternative is not to use dynamic allocation at all and just create local instances of A and B on the stack:

int main()
{
   A objA;
   B objB;
   objA.fun1(); // prints: From base class
   objB.fun1(); // prints: From derived class
}

Now onto your questions:

1/ Yes, providing we can either add a member function to the class definition for B or create other objects from objB. Use either the second or third option described in my original answer:

Second option: calling base class implementation:

Add call to A::fun1() to a new member function in class B:

class B : public A
{
public:
   void fun1()
   {
       cout<<"From derived class\n";
   }

   // Call A::fun1
   void base_fun1()
   {
       A::fun1();
   }
};

We can call base_fun1 like so:

   objB.base_fun1(); // prints: From base class

Third option: slicing a B to an A:

   A sliced_obj_B( objB );
   sliced_obj_B.fun1(); // prints: From base class

This requires that A can be copy constructable. That is, we can make a copy of an existing A to create a new A. We can achieve the same effect by casting objB to its base class type:

   static_cast<A>(objB).fun1();

However, casting is not a recommended practice and in general should not be used as a mainstream construct in your code.

2/ No. This is different from the first case. In the previous case B was publicly derived from A, and public derivation is an is-a relationship: a B is an A. So objB, a B instance, could also be considered to be an A instance.

In this case objA is of type A and A is not derived from anything else, hence objA can be considered an A and nothing else. Now you might think we could add a B member to class A. However to construct an A we would now need to construct this B member. In constructing the B member it has to construct it’s A base class sub-object, which now has a B data member, which requires that it constructs this B data member which has an A base class sub-object it has to construct etc., etc., etc. In short we cannot construct an A without constructing a B and we cannot construct a B without constructing an A, so this does not work! We would have to store a pointer or reference to the B, which means that objA would have to be associated with some B object such as objB. It would also mean that class B would also have to provide a B object during construction. The alternative is that the object be associated after object construction using a member function, which would only be possible for pointers as class instance data members of reference types _must_ be initialised during object construction. Of course a more generally useful thing to do would be to store a pointer or reference to an A instance in A, then other derivations could be associated with A instances.

class A
{
public:
   // Default constructor: initialises iOther to a null pointer
   A() : iOther(0) {}

   // Initialise A instances with a pointer to other A object
   explicit A( A * other ) : iOther(other) {}

   // Allow setting/changing of associated other A object
   // (or A sub-class object) after construction.
   void SetOther( A * other ) { iOther = other; }

   // Call fun1 on referenced (pointed to) other A
   void other_fun1()
   {
       if ( 0 != iOther )
       {
         iOther->fun1();
       }
   }

   virtual void fun1()
   {
       cout<<"From base class\n";
   }

   virtual ~A() {}

private:
   A *       iOther; // store pointer to some A instance
};

class B : public A
{
public:
   B() {}

   // Pass another A by pointer to base class
   explicit B(A * other) : A(other) {}

   void fun1()
   {
       cout<<"From derived class\n";
   }
};

class C : public A
{
public:
   C() {}

   // Pass another A by pointer to base class
   explicit C(A * other) : A(other) {}

   void fun1()
   {
       cout<<"From another derived class\n";
   }
};

int main()
{
   C objC;
   B objB(&objC);
   A objA(&objB);
   objA.fun1();        // prints: From base class
   objA.other_fun1();  // prints: From derived class
   objB.other_fun1();  // prints: From another derived class
   objC.other_fun1();  // prints nothing (iOther is null pointer)
   objC.SetOther(&objA);
   objC.other_fun1();  // prints: From base class
}

I have used a pointer to an A (or A sub-class) instance to associate A instances with another A (or A sub-class) object. I have added a constructor to allow setting this other associated A during construction of A instances. It is marked as explicit to prevent it being used to create A objects from A pointers implicitly when the compiler is looking for possible type conversions. Because I have added this constructor the generation of the default constructor by the compiler is suppressed so I have also added a default constructor that sets the other A pointer member to a null pointer value. I added a member function – SetOther to allow the setting of the other pointer after construction. I have ignored doing anything about copy and assignment for this example, excepting the compiler defaults. This is probably not what is required in real code however – it depends on the context of course. The non-virtual member function other_fun1 will call fun1 on the associated other A object if the pointer is not null.

The knock on effect for class B is to add default and single argument constructors to match those of A. I also added a class C, which is like B except it prints a slightly different message to demonstrate the use of multiple derived types. The main function creates one object each of type C, B and A. The first objC is default constructed, so it’s A base class sub-object’s iOther member will be a null pointer. objB is passed objC and objA is passed objB. Calling objA.other_fun1 will call fun1 on objB. Likewise calling other_fun1 on objB will call fun1 on objC. Calling other_fun1 on objC calls nothing initially as its other A pointer (iOther) is default constructed to be a null pointer. However associating it with objA using SetOther and calling other_fun1 again will call fun1 on objA.

The technicalities aside the main point is that you have to associate another object instance with the base type to obtain the extra information to make the call to the derived type because instances of the base type have no knowledge of their derived classes, and even if they did, which one of the many possible sub-classes should they choose? Just because your example has one base class with one derived sub-class does not mean this is the norm. In fact if you are using virtual functions it implies there is a selection of possible behaviours so expect many derivation of the base class. Of course the context of the A part of these other objects is of those objects, not of the A you are associating them with, and the fact that A is storing a reference (pointer) to another A object is almost academic, it could just as well be some other totally unrelated class that stored the A pointer. This may or may not be acceptable.

3/ Sorry this question makes no sense to me. Can what be implemented as a pointer? Do you mean using an A* or B*? If so where? What do you mean by ‘pointer of type class’ and ‘pointer to a class’? Pointers point to objects not classes. We specify the type the pointer points to, so an A* object is a pointer that points to an A type object (which could be a B object as a B is an A because B is publicly derived from A) and a B* object is a pointer that points to a B type object, and int* is a pointer to an int object.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.