Why can't a 'Base Class object' call it's own virtual function? C++
Asked Answered
D

3

6

I've read about virtual functions in C++ and understood how they provide the programmer with access to the member function of derived class using a pointer of base class. (aka Polymorphism).

The questions that have been bothering me are:

  1. Why declare a function with a same name in the base class, if in the end it has to be declared virtual? (Note: I need answers with respect to the polymorphism aspect of virtual functions)
  2. In the code below, if 'virtual display()' is called with a base class pointer (Line 22), it shows an error. Why are virtual functions in C++ so rigid w.r.t. not getting called by base class pointers?

.

#include <iostream>
using namespace std;

class B
{
    public:
       void virtual display()
         { cout<<"Inside base class.\n"; }

};

class D : public B
{
    public:
       void display()
         { cout<<"Inside derived class.\n"; }
};

int main()
{
    B *b;
    D d;

//Line-22    b->display();  Why can't 'b' call it's own display()?

    b = &d; 
    b->display();

    system("pause");
    return 0;
}

Output:

Inside derived class.

Dewaynedewberry answered 2/9, 2014 at 13:11 Comment(2)
you could do it by calling it's base classe before the call to display : b->B::display()Thistly
@CollioTV: Although it's still illegal to do that with an invalid pointer (even if, in this example, it might appear to work by accident).Culliton
C
3

b is a pointer not an object. Initially it didn't point to anything (so indirecting through it is an error); after b = &d, it points to a D object, so using it to call a virtual function will call D's override.

The virtual dispatch mechanism is defined so that the function is chosen based on the type of the actual object that the pointer points to, not the declared type of the pointer. So if it pointed to a B object then it would call B::display; here, it points to a D object, so it calls D::display.

Why declare a function with a same name in the base class, if in the end it has to be declared virtual?

It needs to be declared in the base class so that, when using a pointer to the base class, the compiler knows that it exists. Whether calling the function through the pointer will call the base-class version, or a version overridden by a derived class, depends on the type of the object.

In the code below, if virtual display() is called with a base class pointer (Line 22), it shows an error.

That's because it doesn't point to anything, so using it is an error. If it were to point to a B object, then it would call the function declared in B.

B b_obj;
b = &b_obj;
b->display();   // "Inside base class"

Why are virtual functions in C++ so rigid w.r.t. not getting called by base class pointers?

They're not; that's the usual way of calling them. But the pointer must point to a valid object for virtual dispatch to work.

Culliton answered 2/9, 2014 at 13:26 Comment(1)
Thanks for explaining the 'virtual dispatch mechanism' in a single line.Dewaynedewberry
H
0

I confess I don't quite understand your question #1. Declaring a virtual function in a base class allows derived classes to override that implementation.

There are tons of uses for this (just search for polymorphism, Liskov substitution etc.). As a simple (and contrived) example, consider this:

struct File
{
  virtual void open() { some_code; }
  virtual void close() { some_code; }

  static std::unique_ptr<File> create();
};

struct DbgFile : File
{
  virtual void open() { std::clog << "Opening"; File::open(); }
  virtual void open() { std::clog << "Closing"; File::close(); }
};

std::unique_ptr<File> File::create()
{
#ifdef NDEBUG
  return { new File };
#else
  return { new DbgFile };
#endif
}

int main()
{
  auto f = File::create();
  f->open();
  f->close();
}

The above main() uses the File interface, but in debug builds, it will actually work with an object of type DbgFile which logs all operations happening on it.


As to your question #2, the problem in your code is that b doesn't point anywhere. If you do this instead, it will work just fine:

int main()
{
    B *b;
    B bb;
    D d;

    b = &bb;
    b->display();  // Outputs "Inside base class."

    b = &d; 
    b->display();  // Outputs "Inside derived class."

    // In addition, you can explicitly suppress dynamic dispatch:
    b->B::display();  // Outputs "Inside base class."

    return 0;
}
Heliogravure answered 2/9, 2014 at 13:15 Comment(1)
with your last update, I could easily correlate virtual functions and polymorphism. Tx.Dewaynedewberry
T
0

Why declare a function with a same name in the base class, if in the end it has to be declared virtual? (Note: I need answers with respect to the polymorphism aspect of virtual functions)

It's necessary because,base class has to know which function definition it needs to call at runtime. Its a kind of interface.

In the code below, if 'virtual display()' is called with a base class pointer (Line 22), it shows an error. Why are virtual functions in C++ so rigid w.r.t. not getting called by base class pointers?

Since the pointer is not initialized its throwing an error. Use like below.

Base baseObj1,*basePtr;

basePtr= &baseObj1;

basePtr->Display();  //Inside base class
Trivium answered 5/9, 2014 at 9:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.